ORDER BY 会将窗口帧从全分区求和自动切换为逐行累计,默认启用 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW;不写 ORDER BY 时 SUM() OVER (PARTITION BY x) 对整个分区求和,结果每行相同。

ORDER BY 一加,窗口帧就从“全分区”变成“逐行累计”
不写 ORDER BY 时,SUM() OVER (PARTITION BY x) 默认对整个分区求和,每行结果都一样;一旦加上 ORDER BY y,数据库立刻切换到“按排序顺序逐行推进”的模式,默认帧变为 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW——这不是你显式写的,是 SQL 标准规定的隐式行为。
这个转换不是语法糖,而是语义切换:前者是分组聚合,后者是累计计算。很多人以为只是“顺便排个序”,结果发现累计值突然跳变,其实是因为 ORDER BY 触发了整套窗口帧重定义。
- PostgreSQL、SQL Server、Oracle 全部遵循该规则,无例外
- 哪怕只写
ORDER BY y不带任何ROWS或RANGE,帧也已隐式生效 - 想保留“全分区求和”又需要排序(比如为后续
ROW_NUMBER()铺路),得显式写死帧:SUM(x) OVER (PARTITION BY a ORDER BY b ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
ORDER BY 字段不唯一 → 累计结果不可复现
当 ORDER BY date 遇到多条同日期记录,数据库可自由决定它们的相对顺序——这直接导致 CURRENT ROW 的位置漂移,累计和在重跑、分页、不同节点上可能完全不同。
例如两笔订单同为 '2026-08-25',引擎这次把 A 排前、B 排后,下次反过来,A 的累计值就包含或不包含 B,静默偏差就此产生。
- 必须补唯一键:优先用主键
id,或业务上确定唯一的组合,如ORDER BY created_at, id -
ORDER BY created_at DESC, id DESC比单用时间更安全,尤其在高并发写入场景 - 别依赖
RANGE救急——它会把所有同日期记录打包进同一帧,让“累计”变成“当天爆发式累加”
ROWS 和 RANGE 在 ORDER BY 后的行为分裂比想象中更剧烈
ORDER BY 是 ROWS 和 RANGE 的共同前提,但两者在它之下走向完全不同的计算逻辑:前者数“第几行”,后者数“值差多少”。一旦排序字段有重复,差异立刻放大。
比如 SUM(sales) OVER (ORDER BY amount ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) 只取物理上前一行 + 当前行;换成 RANGE 后,所有 amount = 当前行值 的记录全被拉进来,窗口大小失控膨胀。
-
LAG()/LEAD()必须用ROWS,RANGE下“上一行”概念失效 - 时间序列滚动计算(如“过去7天”)务必用
ROWS+ORDER BY event_time,别信RANGE BETWEEN INTERVAL '7 DAYS' PRECEDING——它依赖值连续性,而真实数据常有空档或重复时间戳 - SQL Server 和 Azure SQL 强制要求:只要用了
ROWS或RANGE,ORDER BY就不可省略,否则直接报错
ORDER BY 没索引 → 窗口计算性能断崖下跌
带 ORDER BY 的窗口函数要求数据库对每个分区内部严格排序。若 PARTITION BY a ORDER BY b 缺少对应索引(比如只有 (b, a) 而非 (a, b)),引擎只能走外部排序(External Sort),I/O 和内存开销指数级上升。
一个 100 万行的表,分区字段 region 有 50 个值,排序字段 created_at 无索引,窗口累计可能比全表扫描还慢。
- 建复合索引优先按
PARTITION BY列在前,ORDER BY列在后:INDEX (region, created_at) - 避免在
ORDER BY中使用函数或表达式(如ORDER BY DATE(created_at)),会导致索引失效 - NULL 值会让
ROWS和RANGE都无法稳定定位,尽量提前过滤或用COALESCE(created_at, '1970-01-01')统一处理
OVER 语法,而是每次写 ORDER BY 时都问一句:这个排序字段在业务上是否真能唯一锚定每一行?它有没有 NULL?对应索引是否存在?——漏掉任一环,结果就可能白天正常、晚上出错,或者本地快、生产慢。

















