必须写全 OVER (PARTITION BY group_col ORDER BY sort_col),漏写任一部分会导致跨组取值或逻辑失效;LEAD() 缺 OVER 子句必报错,且窗口函数不可用于 WHERE/HAVING。

直接说结论:用 LEAD() 计算分组后差异值,必须写全 OVER (PARTITION BY group_col ORDER BY sort_col),漏掉 PARTITION BY 或 ORDER BY 会导致跨组取值或结果错乱,不是“差一点不准”,而是业务逻辑完全失效。
LEAD() 报错 ERROR: window function LEAD requires an OVER clause 怎么修
这个错误只说明一件事:你写了 LEAD(col) 却没加 OVER。它不是语法警告,是硬性报错,所有主流数据库(MySQL 8.0+、PostgreSQL、SQL Server、Oracle)都如此。
-
LEAD(amount)❌ 不合法,缺OVER -
LEAD(amount) OVER ()❌ 不合法,OVER里必须有ORDER BY -
LEAD(amount) OVER (ORDER BY created_at)✅ 可运行,但仅适用于不分组场景 -
LEAD(amount) OVER (PARTITION BY user_id ORDER BY created_at)✅ 分组 + 排序,才是安全写法
分组内计算“下一笔金额 - 当前金额”时,为什么结果串组了
典型现象:用户 A 的最后一笔订单,和用户 B 的第一笔订单做了减法。根本原因是只写了 ORDER BY created_at,却忘了 PARTITION BY user_id。窗口函数不认“物理插入顺序”,只认 OVER 子句定义的逻辑分区与排序。
- 没加
PARTITION BY→ 整个结果集当一个大组处理 → 跨用户拉数据 -
ORDER BY字段存在重复值(如多条记录created_at相同),且未加唯一辅助排序(如ORDER BY created_at, id)→ 同组内行序不确定 →LEAD()取到哪一行不可控 - 正确写法示例:
LEAD(amount, 1, 0) OVER (PARTITION BY user_id ORDER BY created_at, id),第三个参数0避免末尾行返回NULL干扰后续计算
LEAD() 返回 NULL 导致差异计算出错怎么办
分组最后一行没有“下一行”,LEAD() 默认返回 NULL。如果直接写 LEAD(amount) - amount,结果就是 NULL,可能让 CASE WHEN 判断失效,或聚合时被忽略。
- 显式传第三个参数是最简单解法:
LEAD(amount, 1, 0)返回0,或LEAD(amount, 1, amount)返回自身(表示“无变化”) - 别依赖
COALESCE(LEAD(...), 0)——LEAD()本身支持默认值,额外套函数纯属冗余 - 如果业务上“末尾无下一行”需特殊标记(如
'final'),就用字符串默认值:LEAD(status, 1, 'final'),注意类型要兼容
最容易被忽略的点是:窗口函数只在 SELECT 阶段执行,不能用于 WHERE 或 HAVING。想筛选“下一笔比当前高 500”的记录,必须把 LEAD() 放进子查询或 CTE,再在外层 WHERE 过滤 —— 直接写 WHERE LEAD(...) > amount 必报错。

















