You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;

思路解释:

  1. 用两个CTE分别筛选出目标月和上月的所有国家预算数据
  2. 用FULL OUTER JOIN把两个数据集按国家合并,确保不管当月有没有数据,所有国家都能被覆盖
  3. 用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 10:09:56