rows between 必须配合 order by 才生效,否则窗口按物理顺序取行导致结果不可预测;应优先用 range between interval 做时间聚合,mysql 不支持需用分桶等替代方案。

OVER 子句本身不执行计算,它只是定义“在哪几行上、按什么顺序、怎么分组”来让窗口函数干活——漏写 ORDER BY 或错配 PARTITION BY 是跨行计算失效的最常见原因。
为什么 ROWS BETWEEN 不加 ORDER BY 就报错?
SQL Server 和 Azure SQL 要求:只要用了 ROWS 或 RANGE 子句,ORDER BY 就是强制的。因为“前两行”“后三行”这种说法必须基于明确的排序才有意义。
- 错误写法:
SUM(sales) OVER (PARTITION BY region ROWS BETWEEN 1 PRECEDING AND CURRENT ROW)→ 报错Window frame specification requires an ORDER BY clause - 正确写法:
SUM(sales) OVER (PARTITION BY region ORDER BY sale_date ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) -
RANGE虽然允许省略ORDER BY(但极少用),实际中几乎总要配ORDER BY,否则语义模糊
PARTITION BY 和 GROUP BY 的本质区别
PARTITION BY 不聚合、不减少行数;GROUP BY 会合并行、必须配合聚合函数。这是跨行计算能“每行都出结果”的关键。
- 想看每个部门内员工薪资的累计和?用
PARTITION BY dept_id ORDER BY hire_date,原表 100 行,结果还是 100 行 - 如果误写成
GROUP BY dept_id,就只剩几个部门汇总行,跨行逻辑直接丢失 -
PARTITION BY后的列必须来自FROM子句原始列,不能是SELECT中的别名或表达式,例如PARTITION BY UPPER(name)在 SQL Server 中非法
ROWS 和 RANGE 的行为差异直接影响结果准确性
两者都定义窗口边界,但 ROWS 数物理行,RANGE 数逻辑值范围——遇到重复排序值时,结果可能完全不同。
- 场景:按销售额排序做移动平均,有两人同为 100 万 →
ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING只取相邻三行;RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING会把所有 100 万的记录全拉进来 - 性能上,
ROWS更快更可预测;RANGE在排序键存在大量重复值时容易意外膨胀窗口大小 - 时间序列常用
ROWS(如“过去 7 天”需先用ORDER BY event_time再配ROWS BETWEEN 6 PRECEDING AND CURRENT ROW)
真正难的不是语法拼写,而是想清楚:你要的“跨行”是指“物理相邻行”,还是“值相近的行”;分区依据是否和业务粒度一致;排序字段有没有 NULL 或重复值——这些地方一错,结果就静默偏差,查起来极费劲。










