lag/lead必须搭配order by,否则语法报错;必须用partition by隔离分组,排序字段需加唯一兜底(如id)防重复;首行lag和末行lead默认返回null,可用第三参数设默认值或coalesce处理。

LAG/LEAD 必须带 ORDER BY,否则直接报错
不写 ORDER BY,数据库会立刻抛出 Window function requires an OVER clause with ORDER BY。这不是兼容性问题,而是语法硬性要求——SQL 没有默认行序,“前一行”“后一行”必须由你明确定义。
- 错误写法:
LAG(amount) OVER (PARTITION BY user_id)→ 缺ORDER BY,报错 - 正确写法:
LAG(amount) OVER (PARTITION BY user_id ORDER BY created_at, id)→created_at可能重复,加id保序 - 如果排序字段天然唯一(如自增
id),单用它就够了:ORDER BY id
PARTITION BY 不是可选,漏掉就会跨组拉数据
没加 PARTITION BY,整个结果集当一个窗口处理。比如查每个用户的上一笔订单金额,漏写会导致 A 用户的第二条记录去拉 B 用户的最后一条,完全失真。
- 错误:
LAG(order_amount) OVER (ORDER BY order_time)→ 所有用户混排 - 正确:
LAG(order_amount) OVER (PARTITION BY user_id ORDER BY order_time)→ 每个用户独立计算 -
PARTITION BY字段必须出现在SELECT或GROUP BY中,否则 PostgreSQL 等会报错
第一行 LAG 返回 NULL、最后一行 LEAD 返回 NULL 是正常行为
不是函数出错,而是逻辑上不存在对应行。LAG(col, 1) 在排序后首行必然为 NULL;LEAD(col, 1) 在末行同理。直接参与计算(如 amount - LAG(amount))会导致整列变 NULL。
- 填默认值更安全:
LAG(amount, 1, 0)或COALESCE(LAG(amount), 0) - 注意类型一致:对数值列不能写
LAG(price, 1, 'N/A'),会类型冲突 - 偏移量为 2 时,前两行都返回
NULL,不是“跳过两行”,而是“取上上行”,需确认业务是否真需要该偏移
旧版 MySQL(5.7 及之前)不支持,得用子查询模拟
MySQL 8.0+、PostgreSQL、SQL Server 2012+、Oracle 10g+、SQLite 3.25+ 支持;MySQL 5.7 及更早版本必须绕开。
- 模拟
LAG(取前一行):(SELECT s2.amount FROM sales s2 WHERE s2.date - 关键点:
WHERE s2.date 排除自身和后行;<code>ORDER BY ... DESC LIMIT 1取最接近的前一条 - 性能隐患:每行触发一次子查询,数据量大时明显变慢;建议在
(date, id)上建复合索引 - 若
date不唯一,必须加次级排序字段(如id),否则结果不确定
排序字段重复、PARTITION BY 遗漏、默认 NULL 传导、旧版兼容性——这四点踩中任意一个,LAG/LEAD 就会表现异常,而不是函数本身有问题。











