NTH_VALUE() 函數
NTH_VALUE() 是窗口函數中的位移函數,用來取得窗口範圍內「第 N 列」的值。它是 FIRST_VALUE() 和 LAST_VALUE() 的延伸版本,可以取得任意位置的值。
NTH_VALUE 語法
NTH_VALUE(column, n) OVER (
[PARTITION BY column_name(s)]
ORDER BY column_name(s)
[frame_clause]
)
column: 要取值的欄位n: 要取第幾列的值(從 1 開始)
NTH_VALUE 基本用法 (Example)
假設我們有一個 employees 資料表:
| Dept | Name | Salary |
|---|---|---|
| 業務 | 張一 | 60000 |
| 業務 | 王二 | 55000 |
| 業務 | 李三 | 50000 |
| 研發 | 趙四 | 75000 |
| 研發 | 陳五 | 70000 |
| 研發 | 林六 | 65000 |
取得各部門薪資第 2 高的員工姓名:
SELECT
Dept,
Name,
Salary,
NTH_VALUE(Name, 2) OVER (
PARTITION BY Dept
ORDER BY Salary DESC
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
) AS second_highest
FROM employees;
查詢結果:
| Dept | Name | Salary | second_highest |
|---|---|---|---|
| 業務 | 張一 | 60000 | 王二 |
| 業務 | 王二 | 55000 | 王二 |
| 業務 | 李三 | 50000 | 王二 |
| 研發 | 趙四 | 75000 | 陳五 |
| 研發 | 陳五 | 70000 | 陳五 |
| 研發 | 林六 | 65000 | 陳五 |
窗口框架的重要性
與 LAST_VALUE() 相同,NTH_VALUE() 預設的窗口框架只會看到「當前列及之前」的資料。如果要取得完整分區內的第 N 個值,需要明確指定窗口框架:
-- 正確寫法:指定完整的窗口範圍
NTH_VALUE(column, n) OVER (
ORDER BY column
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
)
當 N 超出範圍時
如果指定的 N 大於窗口內的資料筆數,NTH_VALUE() 會返回 NULL。
-- 如果某部門只有 2 人,取第 3 名會返回 NULL
NTH_VALUE(Name, 3) OVER (PARTITION BY Dept ORDER BY Salary DESC)
實務應用:取得前三名
同時顯示第 1、2、3 名:
SELECT
Dept,
Name,
Salary,
FIRST_VALUE(Name) OVER w AS first_place,
NTH_VALUE(Name, 2) OVER w AS second_place,
NTH_VALUE(Name, 3) OVER w AS third_place
FROM employees
WINDOW w AS (
PARTITION BY Dept
ORDER BY Salary DESC
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
);
使用 WINDOW 子句可以避免重複撰寫相同的窗口定義。
實務應用:中位數近似值
取得排序後中間位置的值:
SELECT
Dept,
NTH_VALUE(Salary, (COUNT(*) OVER (PARTITION BY Dept) + 1) / 2) OVER (
PARTITION BY Dept
ORDER BY Salary
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
) AS median_salary
FROM employees;
資料庫支援度
| 資料庫 | 支援 NTH_VALUE |
|---|---|
| MySQL 8.0+ | ✅ 支援 |
| PostgreSQL | ✅ 支援 |
| SQL Server 2012+ | ✅ 支援 |
| Oracle | ✅ 支援 |
| SQLite 3.25+ | ✅ 支援 |