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

SELECT查询中聚合函数与CASE WHEN用法及销售报表SQL错误排查

SQL问题修正说明

错误点梳理

  • 语法错误1:CASE表达式前多余左括号,无匹配的右括号,导致语法解析失败。
  • 语法错误2:第二个WHEN分支中ROUND函数括号匹配错误,ROUND(SUM(pred_sum)), 2)多了一个右括号,正确写法为ROUND(SUM(pred_sum), 2)。
  • 关联逻辑缺陷:以sales_fact作为主表左联其他表,会丢失「仅存在预测销售额、无实际销售额」的产品月度数据,无法覆盖全量报表场景。
  • 聚合逻辑问题:未对sales_fact、sales_pred先按日期和产品ID单独聚合就直接关联,若同一产品同一天存在多条实际/预测记录,会产生笛卡尔积导致求和结果偏大。
  • 代码冗余:偏差值计算逻辑可通过COALESCE函数大幅简化,无需多层CASE判断。

偏差值逻辑验证

你给出的偏差规则完全可以用 COALESCE(预测销售额,0) - COALESCE(实际销售额,0) 实现,对应规则如下:

  • 实际销售额为null:预测销售额 - 0 = 预测销售额,符合要求
  • 预测销售额为null:0 - 实际销售额 = -实际销售额,符合要求
  • 二者均不为空:预测销售额-实际销售额,符合要求
  • 二者均为空:0-0=0,符合要求

修正后通用版SQL(支持FULL OUTER JOIN的数据库如PostgreSQL、Oracle等)

SELECT 
    COALESCE(YEAR(sf.fact_date), YEAR(sp.pred_date)) AS 年份,
    COALESCE(MONTH(sf.fact_date), MONTH(sp.pred_date)) AS 月份,
    p.name AS 产品名称,
    ROUND(COALESCE(sf.month_fact, 0), 2) AS 实际销售额,
    ROUND(COALESCE(sp.month_pred, 0), 2) AS 预测销售额,
    ROUND(COALESCE(sp.month_pred, 0) - COALESCE(sf.month_fact, 0), 2) AS 偏差值
FROM 
    -- 先聚合计算每个产品每月的实际销售额
    (SELECT 
        prod_id,
        YEAR(fact_date) AS fact_year,
        MONTH(fact_date) AS fact_month,
        SUM(fact_sum) AS month_fact
    FROM sales_fact
    GROUP BY prod_id, fact_year, fact_month) sf
FULL OUTER JOIN 
    -- 先聚合计算每个产品每月的预测销售额
    (SELECT 
        prod_id,
        YEAR(pred_date) AS pred_year,
        MONTH(pred_date) AS pred_month,
        SUM(pred_sum) AS month_pred
    FROM sales_pred
    GROUP BY prod_id, pred_year, pred_month) sp
ON sf.prod_id = sp.prod_id AND sf.fact_year = sp.pred_year AND sf.fact_month = sp.pred_month
-- 关联产品维度表
LEFT JOIN product p ON COALESCE(sf.prod_id, sp.prod_id) = p.prod_id
ORDER BY 年份, 月份, 产品名称;

MySQL适配版SQL(MySQL不支持FULL OUTER JOIN,改用UNION ALL实现)

SELECT 
    year,
    month,
    name,
    ROUND(SUM(month_fact), 2) AS 实际销售额,
    ROUND(SUM(month_pred), 2) AS 预测销售额,
    ROUND(SUM(month_pred) - SUM(month_fact), 2) AS 偏差值
FROM (
    -- 取实际销售数据
    SELECT 
        YEAR(fact_date) AS year,
        MONTH(fact_date) AS month,
        prod_id,
        SUM(fact_sum) AS month_fact,
        0 AS month_pred
    FROM sales_fact
    GROUP BY year, month, prod_id
    UNION ALL
    -- 取预测销售数据
    SELECT 
        YEAR(pred_date) AS year,
        MONTH(pred_date) AS month,
        prod_id,
        0 AS month_fact,
        SUM(pred_sum) AS month_pred
    FROM sales_pred
    GROUP BY year, month, prod_id
) t
LEFT JOIN product p ON t.prod_id = p.prod_id
GROUP BY year, month, name
ORDER BY year, month, name;

内容的提问来源于stack exchange,提问作者user16795517

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 23:18:03