如何编写MySQL查询统计近12个月至本月的每月金额总和?
解决MySQL统计近12个月每月金额总和的问题
嘿,我来帮你搞定这个统计需求~你原来写的语句有两个小问题:一是between last 12 and now()不是MySQL支持的语法,二是缺少按月份分组的逻辑,所以查出来的会是所有符合条件数据的总和,而不是每个月单独的总和。
下面是两种常用的正确写法,你可以根据自己的需求选择:
基础版(只显示有数据的月份)
这个写法适合不需要显示空月份(即某个月没有支出记录就不显示该月)的场景:
SELECT DATE_FORMAT(expense_date, '%Y-%m') AS month, SUM(amount) AS monthly_expense FROM tb_expense WHERE expense_date >= DATE_SUB(NOW(), INTERVAL 12 MONTH) GROUP BY DATE_FORMAT(expense_date, '%Y-%m') ORDER BY month;
语句解释:
DATE_FORMAT(expense_date, '%Y-%m'):把你的日期字段(这里假设是expense_date,如果你的字段名是create_time之类的记得替换)格式化为「年-月」的形式,比如2023-10,这样能区分不同年份的同一个月。SUM(amount) AS monthly_expense:对每个月的amount字段求和,并给结果起一个易读的别名。WHERE expense_date >= DATE_SUB(NOW(), INTERVAL 12 MONTH):筛选出从当前时间往前推12个月至今的所有数据,DATE_SUB(NOW(), INTERVAL 12 MONTH)就是12个月前的此刻时间。GROUP BY DATE_FORMAT(expense_date, '%Y-%m'):按格式化后的月份分组,确保每个月的金额会单独计算总和。ORDER BY month:按月份排序,让结果按时间顺序展示,更直观。
进阶版(显示所有12个月,无数据月份显示0)
如果需要确保过去12个月的每个月都出现在结果里,哪怕某个月没有支出记录也显示金额为0,可以用这个写法:
-- 先生成过去12个月的完整月份列表 WITH months AS ( SELECT DATE_FORMAT(DATE_SUB(NOW(), INTERVAL n MONTH), '%Y-%m') AS month FROM ( SELECT 0 AS n UNION ALL SELECT 1 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 ) AS numbers ) SELECT m.month, COALESCE(SUM(t.amount), 0) AS monthly_expense FROM months m LEFT JOIN tb_expense t ON DATE_FORMAT(t.expense_date, '%Y-%m') = m.month GROUP BY m.month ORDER BY m.month;
语句解释:
- 先用CTE(
WITH months AS ...)生成过去12个月的所有月份,确保每个月都有记录。 - 通过
LEFT JOIN把月份列表和支出表关联,即使某个月没有支出数据,也能保留该月的记录。 COALESCE(SUM(t.amount), 0):如果某个月没有数据,SUM(t.amount)会返回NULL,用COALESCE把它替换成0,结果更友好。
另外补充一下:你原来用的BETWEEN语法如果要正确写的话,应该是BETWEEN DATE_SUB(NOW(), INTERVAL 12 MONTH) AND NOW(),但因为我们要统计的是「至今」的数据,用>= DATE_SUB(...)会更简洁,效果是一样的。
内容的提问来源于stack exchange,提问作者Roth
相关产品推荐
相关产品推荐

