SQL Server 2012 引入 ANSI SQL 2008 標準的 LEAD() 與 LAG() 視窗函數,可在不自聯結的情況下存取同一結果集中其他列的值,極大簡化同比、環比、差值計算等邏輯。
LEAD (scalar_expression [, offset [, default] ]) OVER ( [ partition_by_clause ] order_by_clause )
LAG (scalar_expression [, offset [, default] ]) OVER ( [ partition_by_clause ] order_by_clause )
scalar_expression:要取得的運算式(通常為欄位)offset:向後/向前幾列(預設 1),不可為負數default:超出範圍時回傳值(預設 NULL)OVER 子句必須包含 ORDER BY,可選 PARTITION BYDECLARE @TestData TABLE(
ID INT IDENTITY(1,1),
Department VARCHAR(20),
LastName VARCHAR(20),
Rate FLOAT
);
INSERT INTO @TestData(Department,LastName,Rate) VALUES
('Document Control','Arifin',17.7885),
('Document Control','Norred',16.8269),
('Document Control','Kharatishvili',16.8269),
('Information Services','Chai',10.25),
('Information Services','Berge',10.25),
('Information Services','Trenary',50.4808),
('Information Services','Conroy',39.6635),
('Information Services','Ajenstat',38.4615),
('Information Services','Wilson',38.4615),
('Information Services','Connelly',32.4519),
('Information Services','Meyyappan',32.4519);
SELECT
ID, Department, LastName, Rate,
LEAD(LastName) OVER (ORDER BY ID) AS NextUser
FROM @TestData;
結果:第 1 列顯示第 2 列的 LastName,以此類推;最後一列為 NULL。
LEAD(LastName, 2) OVER (ORDER BY ID) -- 取得第 3 列的值
LEAD(LastName, 1, 'N/A') OVER (ORDER BY ID) -- 最後一列顯示 'N/A' 而非 NULL
SELECT
ID, Department, LastName, Rate,
LAG(LastName) OVER (ORDER BY ID) AS PrevUser
FROM @TestData;
結果:第 1 列為 NULL,第 2 列顯示第 1 列的 LastName。
SELECT
ID, Department, LastName, Rate,
LEAD(Rate) OVER (PARTITION BY Department ORDER BY ID) AS NextRateInDept,
Rate - LAG(Rate) OVER (PARTITION BY Department ORDER BY ID) AS RateDiff
FROM @TestData;
依部門分組,計算組內下一筆薪資與差值,適用於部門內薪資趨勢分析。
LEAD(col, -1) 會報錯,需改用 LAG(col, 1)。ROW_NUMBER() 替代。善用 LEAD/LAG 可將複雜的列間運算轉為清晰的宣告式 SQL,提升可讀性與維護性。