MySQL使用SUM与子查询计算累计总和异常问题排查
问题分析与解决
你的问题出在变量累加的时机和执行顺序上:原查询里,你把变量初始化和月度分组查询放在同一个层级,但MySQL在处理GROUP BY的时候,@running_total的赋值并不会严格按照你期望的年月顺序来累加——因为SELECT子句的执行是在GROUP BY之后,但变量的更新并没有和分组后的结果行按顺序绑定,导致每个月的running_totals只是等于当月的totals,而不是累计值。
修复后的查询语句
我们需要先得到正确的月度汇总数据,再基于这个结果集来计算累计总和:
SELECT month, year, contracts, totals, @running_total := @running_total + totals AS running_totals FROM ( -- 第一步:先计算每个月的汇总数据 SELECT MONTHNAME(app_date) AS month, YEAR(app_date) AS year, COUNT(loan_id) AS contracts, SUM(price * term) AS totals FROM _loans GROUP BY YEAR(app_date), MONTH(app_date) ORDER BY YEAR(app_date), MONTH(app_date) ) AS monthly_summary JOIN (SELECT @running_total := 0) AS init ORDER BY year, MONTH(STR_TO_DATE(month, '%M'));
为什么这样能解决问题?
- 先做月度汇总:内层查询先按年月分组,直接计算每个月的合同数和总金额
totals,得到清晰的月度结果集,避免了原查询中子查询多一层分组的冗余。 - 再计算累计:把这个月度结果集作为数据源,再和初始化的变量
@running_total关联,此时MySQL会按ORDER BY指定的顺序逐行处理,每一行的running_totals都会是之前的累计值加上当月的totals,从而得到正确的累计总和。
验证结果
执行这个查询后,你会得到符合预期的累计值:
| month | year | contracts | totals | running_totals |
|---|---|---|---|---|
| January | 2019 | 6 | 63234.72 | 63234.72 |
| February | 2019 | 10 | 85703.04 | 148937.76 |
| March | 2019 | 4 | 46727.04 | 195664.80 |
内容的提问来源于stack exchange,提问作者ratherBeKiting
相关产品推荐
相关产品推荐

