假設每頁顯示 10 條資料,需查詢第 4 頁的記錄。以下提供兩種常見的分頁實現方式。
利用 ROW_NUMBER() OVER (ORDER BY Id ASC) 為結果集生成連續行號,再透過衍生表篩選目標頁面範圍。
SELECT * FROM (
SELECT ROW_NUMBER() OVER (ORDER BY Id ASC) AS num, *
FROM UserInfo
) AS u
WHERE u.num BETWEEN 10 * (4 - 1) + 1 AND 10 * 4;
優點:語法標準、可讀性強、支援任意排序欄位,SQL Server 2005+ 皆適用。
先排除前 (頁碼-1)*頁大小 條記錄的主鍵,再取前 N 條。
SELECT TOP 10 * FROM UserInfo
WHERE Id NOT IN (
SELECT TOP (10 * 3) Id FROM UserInfo ORDER BY Id
)
ORDER BY Id;
缺點:NOT IN 在大數據量下效能較差;若 Id 含 NULL 會導致結果為空;不支援複雜排序。
| 維度 | ROW_NUMBER() | NOT IN |
|---|---|---|
| 執行計畫 | 單次掃描 + 排序 | 雙重掃描 + 反連接 |
| 百萬級數據 | 秒級 | 可能超時 |
| SQL 版本需求 | 2005+ | 2000+ |
| 複雜排序支援 | 完美 | 困難 |
直接使用 OFFSET ... FETCH 子句,語法最簡潔、效能最優:
SELECT * FROM UserInfo
ORDER BY Id
OFFSET 30 ROWS FETCH NEXT 10 ROWS ONLY;
新專案優先用 OFFSET/FETCH,舊版環境首選 ROW_NUMBER(),避免使用 NOT IN 分頁。