SQL 分组查询中如何计算累计值?

来源:站长论坛作者:重启一下头衔:草根站长
导读:本期聚焦于小伙伴创作的《SQL 分组查询中如何计算累计值?》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《SQL 分组查询中如何计算累计值?》有用,将其分享出去将是对创作者最好的鼓励。

在SQL的实际业务查询中,我们常常需要在分组的前提下计算累计值,比如统计每个部门内员工薪资的累计总和、每个用户每月消费金额的累计变化等。这类需求如果处理不当,很容易写出复杂度高、执行效率低的查询语句,下面介绍两种主流的实现方式。

SQL 分组查询中如何计算累计值?

准备测试数据

首先我们创建一个销售记录表,用于后续的查询示例,表结构包含销售分组、销售日期和当日销售额三个字段:

-- 创建销售记录表
CREATE TABLE sales_record (
    group_id INT COMMENT '分组ID',
    sale_date DATE COMMENT '销售日期',
    sale_amount DECIMAL(10,2) COMMENT '当日销售额'
);

-- 插入测试数据
INSERT INTO sales_record (group_id, sale_date, sale_amount) VALUES
(1, '2024-01-01', 100.00),
(1, '2024-01-02', 150.00),
(1, '2024-01-03', 200.00),
(2, '2024-01-01', 80.00),
(2, '2024-01-02', 120.00),
(2, '2024-01-03', 90.00);

方案一:使用窗口函数计算分组累计值

窗口函数是SQL中处理分组内排序、累计等场景的高效工具,我们可以通过SUM()窗口函数结合OVER子句实现分组累计值的计算,语法逻辑清晰,执行效率也更高。

语法说明

核心语法结构为:SUM(计算字段) OVER (PARTITION BY 分组字段 ORDER BY 排序字段 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW),其中PARTITION BY指定分组的依据,ORDER BY指定分组内排序的规则,ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW表示计算从分组第一行到当前行的累计值。

示例查询

下面的查询会按分组ID分组,按销售日期排序,计算每个分组内的销售额累计值:

SELECT
    group_id,
    sale_date,
    sale_amount,
    -- 计算每个分组内的销售额累计值
    SUM(sale_amount) OVER (
        PARTITION BY group_id
        ORDER BY sale_date
        ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
    ) AS cumulative_amount
FROM sales_record
ORDER BY group_id, sale_date;

执行上述查询后,得到的结果如下:

group_idsale_datesale_amountcumulative_amount
12024-01-01100.00100.00
12024-01-02150.00250.00
12024-01-03200.00450.00
22024-01-0180.0080.00
22024-01-02120.00200.00
22024-01-0390.00290.00

方案二:使用自连接计算分组累计值

如果数据库版本不支持窗口函数,也可以通过自连接的方式实现分组累计值的计算,这种方式兼容性更好,但查询逻辑相对复杂一些。

实现逻辑

将销售记录表自身连接,连接条件为分组ID相同,且右表的销售日期小于等于左表的销售日期,然后按左表的分组ID、销售日期、销售额分组,对右表的销售额求和,即可得到每个分组内的累计值。

示例查询

SELECT
    a.group_id,
    a.sale_date,
    a.sale_amount,
    SUM(b.sale_amount) AS cumulative_amount
FROM sales_record a
INNER JOIN sales_record b
    ON a.group_id = b.group_id
    AND b.sale_date <= a.sale_date
GROUP BY a.group_id, a.sale_date, a.sale_amount
ORDER BY a.group_id, a.sale_date;

该查询的结果和窗口函数方案的结果完全一致,不过当数据量较大时,自连接会产生较多的中间结果,执行效率不如窗口函数方案。

两种方案的选择建议

  • 如果使用的数据库支持窗口函数,比如MySQL 8.0+、PostgreSQL、SQL Server等,优先选择窗口函数方案,代码更简洁,执行效率更高。
  • 如果数据库版本较低不支持窗口函数,比如MySQL 5.7及以下版本,可以选择自连接方案实现需求。
  • 如果累计值需要计算到当前行的前N行,窗口函数可以通过调整ROWS子句的范围灵活实现,自连接方案则需要额外添加日期差的条件,复杂度会进一步提升。

SQL分组查询累计值窗口函数修改时间:2026-07-13 20:24:33

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。