1. 程式人生 > 實用技巧 >Sql server lead和lag

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