首页/数据/SQL 速查/LEAD 取下一行值
聚合与窗口函数54 条

LEAD 取下一行值

取当前行之后第 N 行的值:计算截止时间、下次登录间隔、流程步骤耗时等场景。

SQL 速查数据更新于 2026-10-13

取下一行的值

错行取值是计算相邻记录关系的标准手段:把下一行的时间戳取到当前行,两者相减就是这次操作的持续时长;相邻两条日志之间做差,就能看出间隔是否异常。这类计算的核心是让窗口有确定的顺序,同一时刻可能有多条记录时还要再加一个次级排序键,否则相邻关系在多次执行间会变化。

基本信息

适用平台MySQL 8.0 / PostgreSQL 12 及以上
函数形式取值函数带表达式、偏移量与默认值三个可选部分
边界行为超出范围时返回默认值,未指定则为空值
排序要求必须给出稳定排序,否则相邻关系不确定
时间差写法MySQL 用专用时间差函数,PostgreSQL 用时间戳相减

典型使用场景

  • 流程耗时:相邻两个节点的时间差就是这一步的耗时
  • 登录间隔:上次登录与本次登录的时间差
  • 异常检测:连续两次操作间隔过短,可能为脚本行为
  • 分页游标:取下一行的主键作为下一页的起始位置
  • 任务排队分析:相邻任务之间的等待时长

取值与求差

取值与求差
-- 取下一行的时间戳并求间隔(MySQL 写法)
SELECT id, started_at,
       LEAD(started_at) OVER (ORDER BY started_at) AS next_started,
       TIMESTAMPDIFF(SECOND, started_at,
                     LEAD(started_at) OVER (ORDER BY started_at)) AS gap_seconds
FROM jobs
ORDER BY started_at;

-- PostgreSQL:时间戳直接相减得到间隔
-- SELECT id, started_at,
--        LEAD(started_at) OVER (ORDER BY started_at) AS next_started,
--        EXTRACT(EPOCH FROM (LEAD(started_at) OVER (ORDER BY started_at) - started_at))
--        AS gap_seconds
-- FROM jobs ORDER BY started_at;

-- 指定偏移量与边界默认值:取后两行,末行给默认值
SELECT id, LEAD(id, 2, -1) OVER (ORDER BY id) AS next2 FROM jobs;

-- 按业务对象分组计算间隔
SELECT user_id, login_at,
       login_at - LAG(login_at) OVER (PARTITION BY user_id ORDER BY login_at) AS gap
FROM login_logs;

参数与行为

写法含义边界行为
取值函数无参数取下一行同列的值末行返回空值
指定偏移量取向后第若干行超出范围返回空值
指定默认值超出范围时返回该值便于计算时避免空值
按分区分组每个分组内独立取值分组边界处会出现空值
时间差函数按秒等单位求差PostgreSQL 用时间戳相减再提取
末行取值结果为空值,参与算术运算会让整行结果为空。做平均值或求和统计时要么过滤掉这些行,要么用默认值填充,否则统计口径会悄悄少一行。
排序键相同的情况下,相邻关系取决于数据库的实际执行顺序。计算间隔这类对相邻关系敏感的指标时,一定要把主键之类的唯一列作为次级排序键。

易错点

  • 排序不稳定:同一时刻有多条记录时相邻关系不确定,间隔计算结果每次执行可能不同
  • 末行取值为空导致参与运算后整行结果为空,统计时被静默过滤掉
  • 把时间差函数直接搬到 PostgreSQL:函数名不存在,需要改成时间戳相减再提取秒数
  • 按业务对象分组却忘了指定分区,不同对象的记录被串在一起算间隔
  • 在时间戳字段上做隐式字符串转换,比较与相减结果出错

数据来源与参考

  • MySQL 8.0 Reference Manual · LEAD
  • PostgreSQL Documentation · Window Functions
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌