Sql server lead和lag

lead:取当前行所在位置后指定偏移量的行的值

如 lead(Name,1)取该行后第1行的Name值,lead(Name,10)取该行后第10行的Name值,如果没有返回null

 

lag:取当前行所在位置前指定偏移量的行的值

如 lag(Name,1)取该行前第1行的Name值,lag(Name,10)取该行前第10行的Name值,如果没有返回null

 

示例:

创建测试表

if object_id('tempdb..#TestTable','U') is not null
    drop table tempdb.#TestTable
go
create table #TestTable(Id int,Age int,Name nvarchar(20))

insert into #TestTable(Id,Age,Name)
values(1,10,'A1'),(2,10,'B1'),(3,10,'C1'),(4,41,'D1')

使用lead和lag查询如下:

select * from #TestTable
-- lead和lag函数示例
select Id
    ,LEAD(Name,1) over(order by Id) 'nextName_IdAsc'
    ,LEAD(Name,1) over(order by Id desc) 'nextName_IdDesc'
    ,LEAD(Name,1) over(partition by Age order by Id desc) 'nextName_PAge_IdDesc'
    ,LAG(Name,1) over(order by Id) 'preName_IdAsc'
    ,LAG(Name,1) over(order by Id desc) 'preName_IdDesc'
    ,LAG(Name,1) over(partition by Age order by Id desc) 'preName_PAge_IdDesc'
from #TestTable

查询结果:

 lead/lag查询结果集分析:

首先得知道,lead和lag是使用over处理后的结果集来取值的,over内部先根据partition分区(如果没有显示指定partition,则整个结果集为一个区),分好区后根据order by指定的排列顺序对分区完成的临时结果集进行排序,然后从1开始为排好序的每1行递增分配序号生成新的临时结果集B,lead(lag)就使用有序号的临时结果集B取后(前)几行的数据了

看 nextName_IdAsc列的输出原理:

取值逻辑为LEAD(Name,1) over(order by Id),取值过程为先对表#TestTable分为1个区(因为没有显示指定partition by),然后根据id值(order by id)升序分配序号(序号从1开始递增),分配好的序号结果集B如下:

 接着根据Id定位初始位置所在的行,应用lead的逻辑即取下1行的Name值,即Id为3取下一行Name为D1,Id为2取到C1,Id为1取到B1,Id为4没有下一行返回null;

看 nextName_IdDesc列的输出原理:

nextName_IdDesc取值逻辑为LEAD(Name,1) over(order by Id desc),先对表#TestTable分为1个区,然后根据Id值降序排序分配序号

,分配好的序号结果集如下:

 接着根据Id值定位初始位置所在行,应用lead的逻辑即取下1行的Name值,Id为3取下行为B1,id为2下行取A1,id为1下行取null,id为4下行取C1;

看 nextName_PAge_IdDesc列的输出原理:

nextName_PAge_IdDesc取值逻辑为LEAD(Name,1) over(partition by Age order by Id desc) ,先对表#TestTable根据Age分区,由表数据可知分为2个区(因为age只有10和41),然后在分好的每一个区内根据Id降序分配序号,

分配好的序号如下

 返回结果集分析

接着根据Id定位初始位置所在的行,应用lead的逻辑即取下1行的Name值,id为3取下行为B1,id为2取下行为A1,id为1取下行无返回null,id为4取下行返回null;

同理看 preName_IdAsc列的输出原理:

preName_IdAsc取值逻辑为LAG(Name,1) over(order by Id) ,先对表#TestTable分为1个区,然后根据Id值升序排序分配序号,分配好的序号结果集如下:

分配好的序号如下(与nextName_IdAsc分配好的序号一样)

  接着根据Id定位初始位置所在的行,应用lag的逻辑即取前1行的Name值,即Id为3取前一行Name为B1,Id为2前一行取到A1,Id为1无前一行返回null,Id为4取前一行返回C1;

 

同理,剩下的根据以上类推就能得到了

 

微软文档

https://docs.microsoft.com/en-us/sql/t-sql/functions/lead-transact-sql?view=sql-server-ver15

posted @ 2021-01-03 11:07  温故纳新  阅读(569)  评论(0编辑  收藏  举报