MySQL按月份统计指定课程年度捐款,无捐款月份显示0
解决方案:按月份统计课程捐款(补全无捐款月份)
刚好处理过不少这种需要补全时间维度缺失数据的场景,我来给你一步步解决这个问题:
先明确你的数据源
假设你的表名为donations,现有结构和数据如下:
| id | course_id | amount | created_on |
|---|---|---|---|
| 1 | 2 | 100 | 2018-01-03 |
| 2 | 1 | 300 | 2018-03-03 |
| 3 | 2 | 200 | 2018-01-03 |
| 4 | 4 | 400 | 2018-04-03 |
核心思路
要实现“无捐款月份显示0”的需求,关键是先生成1-12月的完整月份列表,再和你的捐款统计结果做左连接——这样哪怕某个月份没有对应捐款数据,也能保留该月份的记录,最后用COALESCE把空值转为0。
完整SQL代码
-- 生成1到12月的完整月份序列 WITH months AS ( SELECT 1 AS month UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL SELECT 12 ) SELECT m.month, -- 把NULL转为0,确保无捐款月份显示0 COALESCE(SUM(d.amount), 0) AS amount FROM months m -- 左连接捐款表,关联条件:月份匹配+指定课程ID+可选年份筛选 LEFT JOIN donations d ON MONTH(d.created_on) = m.month AND d.course_id = ? -- 这里替换为你要传入的course_id参数 AND YEAR(d.created_on) = 2018 -- 如果需要限定统计某一年,保留此行;否则删除 GROUP BY m.month ORDER BY m.month;
代码解释
- 生成月份序列:用CTE(
WITH子句)创建一个包含1-12月的临时表,这是补全缺失月份的基础。 - 左连接关联:用
LEFT JOIN确保所有月份都被保留,哪怕没有对应的捐款记录。关联条件里指定了course_id参数,以及可选的年份(比如你示例里的2018年)。 - 处理空值:
COALESCE(SUM(d.amount), 0)会把没有捐款的月份的SUM结果(NULL)转换成0,完全符合你的预期输出。 - 排序:最后按月份排序,保证结果是1到12月的顺序。
示例输出(以传入course_id=2为例)
| month | amount |
|---|---|
| 1 | 300 |
| 2 | 0 |
| 3 | 0 |
| 4 | 0 |
| 5 | 0 |
| 6 | 0 |
| 7 | 0 |
| 8 | 0 |
| 9 | 0 |
| 10 | 0 |
| 11 | 0 |
| 12 | 0 |
内容的提问来源于stack exchange,提问作者Jerin Monish
相关产品推荐
相关产品推荐

