lead函数用于获取当前行之后某一行的字段值,必须配合over子句使用,基本语法为lead(column_name, offset, default_value) over (order by sort_column),其中offset默认为1、default_value默认为null,且需配合partition by实现分组内独立计算。

LEAD函数的基本用法和参数含义
LEAD函数用来取当前行之后的某一行字段值,核心是靠ORDER BY定义的逻辑顺序,不是物理存储顺序。它必须配合OVER()子句使用,否则会报错Window function requires an OVER clause。
最简形式:LEAD(column_name, offset, default_value) OVER (ORDER BY sort_column),三个参数分别表示:要取哪列、跳几行(默认1)、越界时返回什么(默认NULL)。
-
offset为1时取下一行;设为2就是下下一行,但要注意窗口范围是否足够 -
default_value建议显式写出,比如LEAD(amount, 1, 0),避免NULL参与后续计算出错 -
ORDER BY列必须有确定性,如果存在重复值且没加唯一键,结果可能不稳定
分区(PARTITION BY)下LEAD怎么不跨组取值
在按用户、日期、类别分组分析时,如果不加PARTITION BY,LEAD会把整张表当一个大窗口排序,导致A用户的下一行可能是B用户的数据——这通常不是你想要的。
正确做法是在OVER()里加上PARTITION BY user_id ORDER BY create_time,这样每个user_id内部独立编号,LEAD只在同组内找下一条。
- 分区列和排序列最好一起建复合索引,否则
OVER()性能容易变差 - MySQL 8.0+ 和 PostgreSQL 支持此写法;SQL Server 也支持;但旧版MySQL(
- 如果分区后某组只有一行,
LEAD()必然返回default_value或NULL,需提前判断
LEAD和LAG混用时的常见陷阱
有人想用LEAD()算“下一笔金额变化”,同时用LAG()算“上一笔”,结果发现同一行里两个函数的ORDER BY方向不一致,导致错位。本质问题是:LEAD和LAG共享同一个排序上下文,但偏移方向相反。
- 只要
OVER()子句完全一致(包括PARTITION BY和ORDER BY),LEAD(1)和LAG(1)就天然对称,无需额外处理 - 错误写法:
LEAD(val) OVER (ORDER BY ts ASC)和LAG(val) OVER (ORDER BY ts DESC)——这会让两函数基于不同顺序计算,结果不可控 - 实际场景中,比如计算环比,直接写
val - LAG(val, 1) OVER (ORDER BY dt)比先LEAD再减更安全
NULL值影响和空行处理策略
当原始数据里ORDER BY字段有NULL,不同数据库行为不一:PostgreSQL默认把NULL排最前,MySQL 8.0默认排最后,SQL Server取决于SET ANSI_NULLS。这会导致LEAD取到的“下一行”意外跳过或错位。
- 稳妥做法是显式控制NULL位置,例如
ORDER BY COALESCE(create_time, '1970-01-01')或ORDER BY create_time DESC NULLS LAST(PostgreSQL/Oracle支持) - 如果业务上不允许NULL时间戳,建表时就该加
NOT NULL约束,比运行时补救更可靠 - LEAD返回NULL本身不可怕,可怕的是后续做
+、/运算时不检查,直接产出NULL结果——建议关键计算前用COALESCE(LEAD(...), 0)兜底
LEAD函数看着简单,真正落地时排序稳定性、分区边界、NULL处理这三点最容易漏掉。尤其在报表或ETL任务里,差一行数据可能让整个趋势线跑偏。










