MySQL中生成年度季度报表并按季度求和的查询问题排查
解决MySQL年度季度报表按季度求和的问题
我来帮你梳理下当前SQL的问题,然后给出更靠谱的解决方案:
原SQL的核心问题
- 月份条件逻辑错误:你用
AND连接多个月份(比如bl.month = 'January' and bl.month = 'Feburary'),这永远匹配不到任何数据——一条记录的月份不可能同时等于两个不同值,应该用IN或者OR - 重复关联导致笛卡尔积:多次LEFT JOIN同一张
bldetails表,会让数据行重复膨胀,最终SUM出来的结果会远大于实际值 - 冗余条件+拼写错误:存在重复的月份判断,还有
Feburary的拼写错误(正确是February)
优化后的解决方案:使用条件聚合
不需要多次关联表,直接在SUM里用CASE WHEN判断记录所属季度,这样既简洁又不会出现数据重复计算的问题:
SELECT t.name as terminals, SUM(CASE WHEN bl.month IN ('January', 'February', 'March') THEN bl.barrels_net_qty ELSE 0 END) as '1ST QTR', SUM(CASE WHEN bl.month IN ('April', 'May', 'June') THEN bl.barrels_net_qty ELSE 0 END) as '2ND QTR', SUM(CASE WHEN bl.month IN ('July', 'August', 'September') THEN bl.barrels_net_qty ELSE 0 END) as '3RD QTR', SUM(CASE WHEN bl.month IN ('October', 'November', 'December') THEN bl.barrels_net_qty ELSE 0 END) as '4TH QTR', SUM(COALESCE(bl.barrels_net_qty, 0)) as total FROM loadingdetails as l LEFT JOIN bldetails as bl ON bl.operation_no = l.operation_no AND l.year = '2020' LEFT JOIN terminals as t ON t.id = l.terminal_id WHERE l.year = '2020' -- 统一过滤2020年的数据,也可以放在JOIN条件里 GROUP BY t.name;
代码说明
- 条件聚合:通过
CASE WHEN把每个季度的月份归组,只对对应季度的barrels_net_qty求和,自动忽略其他季度的数据 - 避免笛卡尔积:只关联一次
bldetails表,不会产生数据行重复的问题 - 简化逻辑:把年份条件统一处理,避免重复写在多个JOIN里
- Total计算简化:直接对所有非空的
barrels_net_qty求和,和四个季度的和结果一致,更简洁
如果你的month字段是数字类型(比如1-12),可以把判断改成bl.month BETWEEN 1 AND 3这种形式,效率会更高。
内容的提问来源于stack exchange,提问作者Emmanuel
相关产品推荐
相关产品推荐

