SQL Server 2012 大幅增強視窗函數 (OLAP/分析函數)。本文從 聚合函數對比 切入,詳細說明語法結構、四大分類、典型應用場景 (分頁、去重、分組 Top N、Running Total、Gaps & Islands) 並展示如何消除 Self-Join 提升效能。
SUM, AVG, COUNT 配合 GROUP BY。COUNT(*) OVER (PARTITION BY Category) → A 每列顯示 5,B 每列顯示 2。
函數() OVER (
PARTITION BY 列1, 列2, ... -- 分區 (可省略,視為單一分區)
ORDER BY 列3, 列4, ... -- 分區內排序 (視函數類型決定是否必填)
[窗口框架子句] -- ROWS/RANGE BETWEEN ... (進階)
) AS 別名
| 分類 | 典型函數 | 用途 |
|---|---|---|
| 排序/排名 | ROW_NUMBER, RANK, DENSE_RANK, NTILE | 分頁、去重、分組 Top N、分桶 |
| 聚合 | SUM, AVG, MIN, MAX, COUNT | Running Total、移動平均、分區統計 |
| 分佈 | PERCENT_RANK, CUME_DIST, PERCENTILE_CONT, PERCENTILE_DISC | 百分位數、累積分佈 |
| 位移 | LAG, LEAD, FIRST_VALUE, LAST_VALUE | 前後行比較、首尾值、Gaps & Islands |
-- 傳統寫法:相關子查詢 / Self-JOIN
SELECT LoginID, Gender,
(SELECT COUNT(*) FROM HumanResources.Employee a WHERE a.Gender = b.Gender) AS GenderTotal
FROM HumanResources.Employee b;
-- 視窗函數寫法:單次掃描
SELECT LoginID, Gender,
COUNT(*) OVER (PARTITION BY Gender) AS GenderTotal
FROM HumanResources.Employee;
ROW_NUMBER() OVER (ORDER BY id) AS rn 篩選 rn BETWEEN ...。ROW_NUMBER() OVER (PARTITION BY Key ORDER BY UpdateTime DESC) AS rn 篩選 rn = 1。rn <= N。SUM(Amount) OVER (PARTITION BY Account ORDER BY TxnDate ROWS UNBOUNDED PRECEDING)。ROW_NUMBER() OVER (ORDER BY Date) - ROW_NUMBER() OVER (PARTITION BY Status ORDER BY Date) 識別連續區間。PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY Salary) OVER (PARTITION BY Dept) 中位數。