使用 rows between current row and unbounded following 配合 order by 和 partition by,可精确计算当前行至分组末尾的累计和;range 不适用,因其按值分组而非行序。

SQL如何获取当前行到结尾的累计值?直接用 ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
SUM() OVER() 默认是从开头累加到当前行,想反向——从当前行一直加到分组末尾(即“剩余累计值”或“后缀和”),必须显式定义窗口帧。关键不是改函数,而是改 ROWS BETWEEN 的起止边界。
常见错误现象:只写 ORDER BY 不写 ROWS,结果还是从前到后累加;或者漏掉 UNBOUNDED FOLLOWING,误用 CURRENT ROW 作终点,导致每行只算自己。
-
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING是唯一能稳定表达“当前行及之后所有行”的语法,它不依赖排序值是否重复,纯按物理行序定位 - 必须配合
ORDER BY,否则数据库无法确定“结尾”在哪(无序集合没有“当前行之后”的概念) - 如果还用了
PARTITION BY,这个“结尾”指当前分组的末尾,不是全表末尾
为什么不能用 RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING?
RANGE 按排序字段的值范围界定窗口,不是按行。当 ORDER BY 字段存在重复值时,RANGE 会把所有同值的行打包进同一窗口——哪怕它们物理上分散在不同位置。
比如按日期 ORDER BY sale_date,若某天有 5 条记录,RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING 会让这 5 行的计算结果完全相同(因为值相等,视为同一逻辑点),失去“逐行递减累计”的意义。
- 要逐行变化的后缀和,必须用
ROWS,不是RANGE -
RANGE适合做“某时间点之后所有同等级数据求和”,但不适合“从当前行开始往后累加”这类明确行序需求 - PostgreSQL、SQL Server、Oracle、MySQL 8.0+ 对
ROWS的行为一致;旧版 MySQL 不支持窗口函数,别踩坑
实战示例:计算每个销售员“从当天起剩余总业绩”
假设表 sales_table 有字段 seller、sale_date、amount,需按人分组、按日期升序排列,然后算“当天及之后所有销售的 amount 总和”:
SELECT
seller,
sale_date,
amount,
SUM(amount) OVER (
PARTITION BY seller
ORDER BY sale_date
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
) AS remaining_cumulative
FROM sales_table;
注意:ORDER BY sale_date 升序决定了“结尾”是日期最晚的那条;如果业务要按时间倒序看“从最新一笔开始往前累计”,就把 ORDER BY 改成 sale_date DESC,再配同样 ROWS 子句即可。
容易被忽略的兼容性与性能点
某些 OLAP 场景下,UNBOUNDED FOLLOWING 在大数据量分组中可能触发全分区扫描,尤其当分组内行数极多且无索引支撑 ORDER BY 字段时。
- 确保
ORDER BY字段上有索引(如复合索引(seller, sale_date)),否则排序开销大 - MySQL 8.0.2+、PostgreSQL 11+、SQL Server 2012+ 均完整支持该语法;Hive 和 Spark SQL 也支持,但 Hive 3.1 前对
UNBOUNDED FOLLOWING解析较弱,建议升级 - 别试图用自连接模拟——逻辑复杂、性能差、易出错;原生窗口函数就是为此而生的
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING,核心就两点:一是严格绑定 ORDER BY,二是确认目标数据库版本支持该窗口帧语法。其余都是围绕这两点做索引和校验。











