LAG() 與 LEAD() 函數
LAG() 和 LEAD() 是窗口函數中的位移函數,用來存取同一結果集中「前幾列」或「後幾列」的資料,常用於比較相鄰資料列之間的差異。
- LAG(): 取得「前面」第 N 列的值
- LEAD(): 取得「後面」第 N 列的值
LAG 語法
LAG(column, offset, default_value) OVER (
[PARTITION BY column_name(s)]
ORDER BY column_name(s)
)
column: 要取值的欄位offset: 往前幾列(預設為 1)default_value: 當沒有前一列時的預設值(選填)
LEAD 語法
LEAD(column, offset, default_value) OVER (
[PARTITION BY column_name(s)]
ORDER BY column_name(s)
)
參數與 LAG() 相同,但方向是往後取值。
LAG 基本用法 (Example)
假設我們有一個 monthly_sales 資料表:
| Month | Sales |
|---|---|
| 1 | 1000 |
| 2 | 1200 |
| 3 | 1100 |
| 4 | 1500 |
使用 LAG() 取得上個月的銷售額來計算成長:
SELECT
Month,
Sales,
LAG(Sales, 1) OVER (ORDER BY Month) AS prev_sales,
Sales - LAG(Sales, 1) OVER (ORDER BY Month) AS growth
FROM monthly_sales;
查詢結果:
| Month | Sales | prev_sales | growth |
|---|---|---|---|
| 1 | 1000 | NULL | NULL |
| 2 | 1200 | 1000 | 200 |
| 3 | 1100 | 1200 | -100 |
| 4 | 1500 | 1100 | 400 |
第一列沒有「前一列」,所以 prev_sales 是 NULL。
設定預設值
可以指定第三個參數作為沒有資料時的預設值:
SELECT
Month,
Sales,
LAG(Sales, 1, 0) OVER (ORDER BY Month) AS prev_sales
FROM monthly_sales;
這樣第一列的 prev_sales 會是 0 而非 NULL。
LEAD 用法 (Example)
使用 LEAD() 取得下個月的銷售額:
SELECT
Month,
Sales,
LEAD(Sales, 1) OVER (ORDER BY Month) AS next_sales
FROM monthly_sales;
查詢結果:
| Month | Sales | next_sales |
|---|---|---|
| 1 | 1000 | 1200 |
| 2 | 1200 | 1100 |
| 3 | 1100 | 1500 |
| 4 | 1500 | NULL |
取得前後 N 列
offset 參數可以指定往前或往後幾列:
SELECT
Month,
Sales,
LAG(Sales, 2) OVER (ORDER BY Month) AS sales_2_months_ago,
LEAD(Sales, 2) OVER (ORDER BY Month) AS sales_in_2_months
FROM monthly_sales;
搭配 PARTITION BY 使用
在各分組內分別計算:
SELECT
Region,
Month,
Sales,
LAG(Sales, 1) OVER (PARTITION BY Region ORDER BY Month) AS prev_sales
FROM regional_sales;
這樣每個地區的「上個月」會各自獨立計算。
實務應用:計算成長率
SELECT
Month,
Sales,
LAG(Sales, 1) OVER (ORDER BY Month) AS prev_sales,
ROUND((Sales - LAG(Sales, 1) OVER (ORDER BY Month)) * 100.0
/ LAG(Sales, 1) OVER (ORDER BY Month), 2) AS growth_rate
FROM monthly_sales;
實務應用:年增率 (YoY)
比較與去年同期的差異:
SELECT
Year,
Month,
Sales,
LAG(Sales, 12) OVER (ORDER BY Year, Month) AS sales_last_year,
Sales - LAG(Sales, 12) OVER (ORDER BY Year, Month) AS yoy_growth
FROM monthly_sales;