SQL Server 2005 引入四個 ANSI SQL 標準排序函數,徹底改變結果集排序與分組編號方式。本文以產品資料表為例,詳細比較四函數語法、行為差異與適用情境。
CREATE TABLE Products (
ProductID INT IDENTITY(1,1) PRIMARY KEY,
Name VARCHAR(50),
Price MONEY
)
INSERT INTO Products (Name, Price) VALUES
('產品A', 100), ('產品B', 200), ('產品C', 200), -- 價格重複測試
('產品D', 300), ('產品E', 400), ('產品F', 500)
SELECT
ProductID, Name, Price,
ROW_NUMBER() OVER (ORDER BY Price DESC) AS RowNum
FROM Products
| Name | Price | RowNum |
|---|---|---|
| 產品F | 500 | 1 |
| 產品E | 400 | 2 |
| 產品D | 300 | 3 |
| 產品B | 200 | 4 |
| 產品C | 200 | 5 |
| 產品A | 100 | 6 |
特性: 無視重複值,嚴格遞增 1,2,3... 最適合分頁查詢。
SELECT
ProductID, Name, Price,
RANK() OVER (ORDER BY Price DESC) AS RankNum
FROM Products
| Name | Price | RankNum |
|---|---|---|
| 產品F | 500 | 1 |
| 產品E | 400 | 2 |
| 產品D | 300 | 3 |
| 產品B | 200 | 4 |
| 產品C | 200 | 4 |
| 產品A | 100 | 6 |
特性: 相同值同排名,下一名次跳過重複筆數。如奧運獎牌排名。
SELECT
ProductID, Name, Price,
DENSE_RANK() OVER (ORDER BY Price DESC) AS DenseRank
FROM Products
| Name | Price | DenseRank |
|---|---|---|
| 產品F | 500 | 1 |
| 產品E | 400 | 2 |
| 產品D | 300 | 3 |
| 產品B | 200 | 4 |
| 產品C | 200 | 4 |
| 產品A | 100 | 5 |
特性: 相同值同排名,下一名次遞增 1。適合「前 N 名」不想因並列而縮減名額的情境。
SELECT
ProductID, Name, Price,
NTILE(3) OVER (ORDER BY Price DESC) AS Bucket
FROM Products
| Name | Price | Bucket |
|---|---|---|
| 產品F | 500 | 1 |
| 產品E | 400 | 1 |
| 產品D | 300 | 2 |
| 產品B | 200 | 2 |
| 產品C | 200 | 3 |
| 產品A | 100 | 3 |
特性: 將排序後資料分成 n 個桶,桶編號 1~n。資料盡量均勻分配,前桶筆數 ≥ 後桶。
DECLARE @PageSize INT = 10, @PageIndex INT = 3
SELECT ProductID, Name, Price
FROM (
SELECT
ProductID, Name, Price,
ROW_NUMBER() OVER (ORDER BY Price DESC) AS RowNum
FROM Products
) AS Paged
WHERE RowNum BETWEEN (@PageIndex - 1) * @PageSize + 1 AND @PageIndex * @PageSize
ORDER BY Price DESC
-- 依類別分組,各組內依價格排名
SELECT
Category, Name, Price,
ROW_NUMBER() OVER (PARTITION BY Category ORDER BY Price DESC) AS RankInCategory
FROM Products
OVER (ORDER BY ...),確保排序欄位有索引可避免 Sort 運算子。ROW_NUMBER() 配合 TOP 或 OFFSET/FETCH(2012+)效能最佳。PARTITION BY 會增加運算複雜度,僅在必要時使用。四大排序函數各有專精領域。ROW_NUMBER() 是分頁王者;RANK()/DENSE_RANK() 解決商業排名報表需求;NTILE() 則是資料分析分組利器。熟練掌握這四把刷子,T-SQL 表達力將大幅提升。