MySQL按商品统计每月销售数量:SQL结果异常求助
解决SQL分组统计每月销量的异常问题
嘿,我一眼就看出你遇到的问题根源了!你的SQL里SUM()函数的位置摆错了,导致它计算的是每个商品的总销量,而不是对应月份的销量。
问题出在哪?
先看你原来的SQL:
SELECT `sales`.`item_id`, (CASE WHEN MONTH(sales.date)=1 THEN sum(sales.item_count) ELSE NULL END) as JAN, (case when MONTH(sales.date)=2 THEN sum(sales.item_count) ELSE NULL END) as FEB FROM sales WHERE 1 GROUP BY sales.item_id ORDER BY sales.item_id;
这里的SUM(sales.item_count)是对整个item_id分组的所有行求和,然后CASE WHEN只是判断这个分组里有没有1月的数据——如果有,就把总销量塞进JAN列,否则放NULL。这就导致你看到的JAN列是该商品的全部销量,FEB列变成NULL(因为分组里同时有1月和2月数据时,第一个CASE满足,第二个不触发)。
正确的写法
你需要把SUM()放到CASE WHEN的内部,让它只对符合月份条件的行的item_count求和:
SELECT item_id, SUM(CASE WHEN MONTH(date) = 1 THEN item_count ELSE 0 END) AS JAN, SUM(CASE WHEN MONTH(date) = 2 THEN item_count ELSE 0 END) AS FEB FROM sales GROUP BY item_id ORDER BY item_id;
简单解释:
- 对每个
item_id分组,CASE WHEN MONTH(date)=1 THEN item_count ELSE 0 END会保留1月份行的item_count,其他月份的行贡献0。 - 外层的
SUM()把这些值加起来,就得到了该商品1月份的真实销量,FEB列同理。 - 用
ELSE 0代替ELSE NULL的好处是,没有对应月份销量时会显示0,而不是NULL,结果更直观。
测试结果
用你的测试数据运行这个SQL,会完美得到你期望的结果:
| item_id | JAN | FEB |
|---|---|---|
| 1 | 11 | 7 |
| 2 | 5 | 3 |
扩展:跨年份的兼容写法
如果你的数据涉及多个年份,建议加上年份判断,避免把不同年份的同月份数据混在一起:
SELECT item_id, YEAR(date) AS sale_year, SUM(CASE WHEN MONTH(date) = 1 THEN item_count ELSE 0 END) AS JAN, SUM(CASE WHEN MONTH(date) = 2 THEN item_count ELSE 0 END) AS FEB FROM sales GROUP BY item_id, YEAR(date) ORDER BY item_id, sale_year;
内容的提问来源于stack exchange,提问作者Rajib Deb
相关产品推荐
相关产品推荐

