LEAD函数用于获取当前行之后第N行的值,必须配合OVER子句及ORDER BY排序使用;基本形式为LEAD(column, offset, default),offset默认为1且须为正整数,default为越界时返回值。

LEAD函数的基本用法和参数含义
LEAD函数用来取当前行之后的某一行数据,核心是靠窗口排序决定“下一条”是谁。它必须配合 OVER 子句使用,否则会报错 Window function requires OVER clause。
最简形式:LEAD(column_name, offset, default_value) OVER (ORDER BY sort_column)
-
column_name:要取值的字段,比如order_amount -
offset:偏移行数,默认为 1,填 2 就取下下条;填 0 是无效的,不会返回当前行 -
default_value:当后面没数据时返回的默认值,不填则返回NULL -
ORDER BY必须明确——业务上“下一条”依赖排序逻辑,比如按created_at或id,不能只靠表物理顺序
按业务时间取下一笔订单金额
常见场景是分析订单时间序列,比如“用户本次下单金额 vs 下次下单金额”。这时候必须确保排序字段能反映真实业务先后顺序。
错误写法:LEAD(amount) OVER (ORDER BY id) —— 如果 id 不是自增或存在删改,顺序就不可靠。
推荐写法:LEAD(amount) OVER (PARTITION BY user_id ORDER BY created_at, id)
-
PARTITION BY user_id防止跨用户混淆,“下一条”只在同一个用户内找 -
ORDER BY created_at, id解决同一秒内多笔订单的排序不确定性 - 如果
created_at有空值,LEAD 会把它们排在最前或最后(取决于数据库),可能打乱业务逻辑,建议提前过滤或用COALESCE(created_at, '1970-01-01')
LEAD返回NULL的几种典型原因
不是函数出错,而是语义结果如此——最后一行天然没有“下一条”,但实际中容易误判为数据缺失。
- 当前行已是分区内的最后一行(如某个用户的最后一条订单)→ 返回
NULL或你指定的default_value -
ORDER BY字段存在重复值且未加二级排序 → 数据库任意取一条作为“下一条”,结果不稳定 - 用了
PARTITION BY但某些分组只有一条记录 → 全部该分组的 LEAD 结果都是NULL - 查询条件
WHERE写在窗口函数外层,导致排序基于全表,但最终只取部分行 → “下一条”可能被过滤掉,LEAD 却仍尝试取它(结果是NULL)
性能和兼容性注意点
LEAD 是标准窗口函数,MySQL 8.0+、PostgreSQL、SQL Server、Oracle 都支持,但 SQLite 默认不支持(需编译启用)。
- 大数据量下,
ORDER BY字段最好有索引,否则排序开销明显 - 避免在
LEAD中嵌套复杂子查询或函数(如LEAD(CASE WHEN ...)),先算好基础字段再窗口计算 - 如果只需要判断“是否存在下一条”,用
COUNT(*) OVER (PARTITION BY ... ORDER BY ... ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING)可能比 LEAD 更轻量
业务逻辑里别假设 LEAD 一定有值,尤其做差值计算时记得用 COALESCE(LEAD(...), 0) 或显式判断 IS NOT NULL——这是最容易漏掉的一环。

















