需求:查詢「成績前 5 名學生」,但成績可並列 (如 3 人同分 99 分),使用 `ROW_NUMBER()` 會強制打散名次,導致前 5 名可能遺漏並列同分者。`DENSE_RANK()` 完美解決:並列同分、名次不跳號、直接篩選 `rank <= 5`。
DECLARE @t TABLE (ID INT, StudentName NVARCHAR(15), Score INT);
INSERT INTO @t VALUES
(1,'黃一',99),(2,'吳二',99),(3,'張三',99),
(4,'李四',98),(5,'王五',97),(6,'趙六',96),
(7,'田七',95),(8,'紀八',94),(9,'邱九',93),(10,'林十',92);
SELECT t1.*
FROM @t t1
JOIN (SELECT DISTINCT TOP 5 Score FROM @t ORDER BY Score DESC) t2
ON t1.Score = t2.Score
ORDER BY t1.Score DESC;
缺點:需額外排序、JOIN 開銷、程式碼冗長。
WITH cte AS (
SELECT
DENSE_RANK() OVER (ORDER BY Score DESC) AS Rank,
*
FROM @t
)
SELECT * FROM cte WHERE Rank <= 5;
結果: 3 位 99 分同為 Rank 1、98 分 Rank 2、97 分 Rank 3、96 分 Rank 4、95 分 Rank 5 → 共 7 筆資料,完美符合「前 5 名含並列」語意。


同樣資料改用 `RANK()`:
SELECT RANK() OVER (ORDER BY Score DESC) AS Rank, * FROM @t;
`RANK()` 適合「競賽名次」語意 (並列佔用名次);`DENSE_RANK()` 適合「分級/分頁/Top N 含並列」語意。

| 函數 | 並列處理 | 名次連續性 | 典型用途 |
|---|---|---|---|
| ROW_NUMBER() | 強制打散 (依次序) | 1,2,3,4... 無間隙 | 分頁、去重、唯一排序 |
| RANK() | 同分同名次 | 有間隙 (1,1,1,4,5...) | 競賽排名、銷售冠軍 |
| DENSE_RANK() | 同分同名次 | 無間隙 (1,1,1,2,3...) | Top N 含並列、等級分級 |
| NTILE(n) | 平均分桶 | 1..n 循環 | 分位數、百分位分組 |
掌握四大排名函數特性,即可用最簡潔 SQL 解決複雜排序分級需求。