AVG() OVER(ORDER BY ... ROWS BETWEEN ...) 是唯一标准写法,必须同时包含 ORDER BY 和 ROWS BETWEEN,缺一不可;仅 ORDER BY 会触发累积平均或报错,ROWS BETWEEN 才能精确定义滑动窗口边界。

AVG() OVER(ORDER BY ... ROWS BETWEEN ...) 是唯一标准写法
没有“其他更标准”的替代方案——AVG() 本身不带滑动能力,必须套进 OVER(),且必须显式写 ROWS BETWEEN。漏掉任意一部分都会出错或结果错乱。ORDER BY 不是可选修饰,而是硬性前提;ROWS BETWEEN 不是语法糖,而是定义窗口边界的唯一可靠方式。
为什么不能只写 ORDER BY 而不加 ROWS BETWEEN
只写 AVG(sales) OVER (ORDER BY date) 在多数数据库(如 SQL Server、PostgreSQL)中会默认按 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 执行,也就是“值相同就全算进来”。如果多条记录共享同一个 date(比如日粒度聚合后仍有重复),它们会被打包进同一窗口,导致某天突然均值飙升,完全不是“滑动3行”的本意。
- MySQL 8.0+ 直接报错:
Window definition requires ORDER BY(提示你缺框架) - PostgreSQL 可能跑通但结果随机——尤其当
date有重复时,物理行序不固定 - 正确写法必须带
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW这类明确边界
ROWS BETWEEN 的数字到底怎么数
N PRECEDING 指“从当前行往上数 N 行”,不包含当前行;CURRENT ROW 是锚点,单独算一行。所以含当前行共 K 行的窗口,N 就是 K−1。
- 3 行移动平均(含当前)→
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW - 5 行中心对称(前2 + 当前 + 后2)→
ROWS BETWEEN 2 PRECEDING AND 2 FOLLOWING - 错误写法:
ROWS BETWEEN 3 PRECEDING AND CURRENT ROW实际是 4 行,不是 3 行 - 首尾几行天然不满额:第 1 行窗口只有 1 行,第 2 行最多 2 行——这是 SQL 标准行为,不是 bug
PARTITION BY 和排序稳定性是线上翻车高发区
漏写 PARTITION BY 或排序字段不唯一,是生产环境最常导致指标错乱的原因。例如按用户算 7 日均值,没加 PARTITION BY user_id,A 用户第一笔订单可能和 B 用户最近 6 笔混在一起算。
- 分组必须显式:
AVG(amount) OVER (PARTITION BY user_id ORDER BY order_time ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) -
ORDER BY必须兜底唯一性:仅ORDER BY order_time不够,要加, order_id或, created_at - 时间字段精度不够(如只有日期)?先用
ROW_NUMBER() OVER (ORDER BY order_date, id)生成稳定序号,再按该序号开窗 - NULL 值会被
AVG()自动跳过,但依然占窗口“槽位”——窗口大小由ROWS定义,不受 NULL 影响

















