MySQL条件查询需求:获取指定月份各国销售预算,缺失时返回上月数据
解决指定月份预算查询,缺失时用上月数据的问题
嘿,这个需求我太懂了!咱们直接来拆解问题:要从budgets表拉取指定月份的各国预算,当月没录入就用上月的,而且绝对不能用“取最新日期”的思路——毕竟需求明确要求只看目标月和它的上月,对吧?
首先先明确下我假设的budgets表结构(如果你的字段名不一样,对应替换就行):
country:国家名称(比如'China'、'USA')budget_month:预算月份,格式是YYYY-MM-01的日期类型budget_amount:预算金额数值
方法一:用CTE+全连接(FULL OUTER JOIN)实现
这个方法最直观,就是分别把目标月和上月的数据拎出来,再合并到一起优先取当月数据:
-- 先定义目标月份,这里以'2018-03-01'为例 WITH target_month_data AS ( SELECT country, budget_amount AS current_budget FROM budgets WHERE budget_month = '2018-03-01' ), prev_month_data AS ( SELECT country, budget_amount AS prev_budget FROM budgets WHERE budget_month = DATE_SUB('2018-03-01', INTERVAL 1 MONTH) -- 计算上月日期 ) SELECT COALESCE(t.country, p.country) AS country, COALESCE(t.current_budget, p.prev_budget) AS budget_amount FROM target_month_data t FULL OUTER JOIN prev_month_data p ON t.country = p.country;
思路解释:
- 用两个CTE分别筛选出目标月和上月的所有国家预算数据
- 用
FULL OUTER JOIN把两个数据集按国家合并,确保不管当月有没有数据,所有国家都能被覆盖 - 用
COALESCE函数优先取当月的预算值,要是当月没数据(也就是current_budget为NULL),就自动用上月的prev_budget
适配MySQL的替代方案(因为MySQL不支持FULL OUTER JOIN)
如果你的数据库是MySQL,那可以用UNION ALL来实现同样的效果:
WITH target_month_data AS ( SELECT country, budget_amount AS budget_amount FROM budgets WHERE budget_month = '2018-03-01' ), prev_month_data AS ( SELECT country, budget_amount AS budget_amount FROM budgets WHERE budget_month = DATE_SUB('2018-03-01', INTERVAL 1 MONTH) ) -- 先取当月有数据的国家 SELECT * FROM target_month_data UNION ALL -- 再取当月没数据,但上月有的国家 SELECT * FROM prev_month_data WHERE country NOT IN (SELECT country FROM target_month_data);
方法二:用窗口函数精准筛选
如果你习惯用窗口函数,也可以这么写,同样完全不依赖“最新日期”逻辑:
SELECT country, budget_amount FROM ( SELECT country, budget_amount, -- 按国家分组,按月份排序,取上一条(也就是上月)的预算 LAG(budget_amount) OVER (PARTITION BY country ORDER BY budget_month) AS prev_budget, -- 给每个国家的两条数据(目标月+上月)按日期倒序排号 ROW_NUMBER() OVER (PARTITION BY country ORDER BY budget_month DESC) AS rn FROM budgets -- 只筛选目标月和上月的数据,避免多余计算 WHERE budget_month IN ('2018-03-01', DATE_SUB('2018-03-01', INTERVAL 1 MONTH)) ) sub_query -- 取每个国家的第一条(也就是日期最新的那条:有当月数据就取当月,没有就取上月) WHERE rn = 1;
思路解释:
子查询里只保留目标月和上月的数据,然后给每个国家的这两条数据按日期倒序排号,最后取排号为1的那条——这样就自动实现了“优先当月,没有就上月”的逻辑,而且全程都是针对指定的两个月份,完全没用到“找最新日期”的逻辑。
内容的提问来源于stack exchange,提问作者Enic
相关产品推荐
相关产品推荐

