You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在MySQL中实现分组内的累计求和(Running Total)

没问题!我来帮你梳理下在MySQL里实现分组累计求和(Running Total)的两种方法,同时满足你排除每个Id对应最大月份记录的需求。

先把你的输入数据贴出来,方便测试验证:

Create table Employee (Id int, Month int, Salary int);
insert into Employee (Id, Month, Salary) values ('1', '1', '20');
insert into Employee (Id, Month, Salary) values ('2', '1', '20');
insert into Employee (Id, Month, Salary) values ('1', '2', '30');
insert into Employee (Id, Month, Salary) values ('2', '2', '30');
insert into Employee (Id, Month, Salary) values ('3', '2', '40');
insert into Employee (Id, Month, Salary) values ('1', '3', '40');
insert into Employee (Id, Month, Salary) values ('3', '3', '60');
insert into Employee (Id, Month, Salary) values ('1', '4', '60');
insert into Employee (Id, Month, Salary) values ('3', '4', '70');

方法一:MySQL 8.0+ 用窗口函数(推荐)

如果你用的是MySQL 8.0或更新的版本,直接用窗口函数就能轻松实现,还能把你原来的SQL优化得更简洁——不用额外左连接子查询,直接用窗口函数获取每个Id的最大月份:

SELECT 
    Id,
    Month,
    SUM(Salary) OVER(PARTITION BY Id ORDER BY Month) AS cumm_sal
FROM Employee
WHERE Month != (MAX(Month) OVER(PARTITION BY Id))
ORDER BY Id, Month DESC;

逻辑拆解:

  • SUM(Salary) OVER(PARTITION BY Id ORDER BY Month):按Id分组,在每个组内按Month从小到大排序,累计计算薪资总和,这就是你要的累计求和。
  • MAX(Month) OVER(PARTITION BY Id):同样按Id分组,直接获取每个用户的最大月份,避免了额外的子查询连接。
  • WHERE Month != ...:过滤掉每个用户最大月份的记录。
  • 最后ORDER BY Id, Month DESC:让每个用户的记录按月份倒序排列,和你的预期输出一致。

运行这段SQL后,就能得到你想要的结果:

| Id | Month | cumm_sal |
|----|-------|----------|
| 1  | 3     | 90       |
| 1  | 2     | 50       |
| 1  | 1     | 20       |
| 2  | 1     | 20       |
| 3  | 3     | 100      |
| 3  | 2     | 40       |

方法二:MySQL 5.x 版本(不支持窗口函数)

如果你的MySQL版本是5.x(不支持窗口函数),那就得用自连接+分组求和的方式来实现:

SELECT 
    e1.Id,
    e1.Month,
    SUM(e2.Salary) AS cumm_sal
FROM Employee e1
JOIN Employee e2 ON e1.Id = e2.Id AND e2.Month <= e1.Month
JOIN (SELECT Id, MAX(Month) AS max_month FROM Employee GROUP BY Id) emax 
    ON e1.Id = emax.Id
WHERE e1.Month != emax.max_month
GROUP BY e1.Id, e1.Month
ORDER BY e1.Id, e1.Month DESC;

逻辑拆解:

  1. 子查询emax:先获取每个Id对应的最大月份,用来后续过滤。
  2. 自连接e1和e2:让每条记录e1关联同一个Id下所有月份小于等于它的记录e2。
  3. SUM(e2.Salary):对关联到的所有e2的薪资求和,就得到了e1这条记录的累计薪资。
  4. WHERE e1.Month != emax.max_month:过滤掉最大月份的记录。
  5. 最后分组排序,得到预期结果。

这个方法虽然代码长一点,但在老版本MySQL里是可行的,运行结果和上面的窗口函数方法完全一致。


内容的提问来源于stack exchange,提问作者Teja

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:42:21