CREATE TABLE table1 (id INT PRIMARY KEY, ...);
NOT IN + 子查詢(經典但低效)SELECT TOP @PageSize *
FROM table1
WHERE id NOT IN (
SELECT TOP @PageSize * (@PageNum - 1) id
FROM table1 ORDER BY id
)
ORDER BY id;
缺點:NOT IN 子查詢每頁重掃;含 NULL 時語義陷阱;大偏移量效能急劇下降。
ID > 最大值 游標式(高效、需連續/單調 ID)-- 正序
SELECT TOP @PageSize *
FROM table1
WHERE id > (
SELECT ISNULL(MAX(id), 0)
FROM (
SELECT TOP @PageSize * (@PageNum - 1) id
FROM table1 ORDER BY id
) t
)
ORDER BY id;
-- 倒序(最新優先,常見於論壇/動態)
SELECT TOP @PageSize *
FROM table1
WHERE id <= (
SELECT ISNULL(MIN(id), (SELECT MAX(id) FROM table1))
FROM (
SELECT TOP @PageSize * (@PageNum - 1) id
FROM table1 ORDER BY id DESC
) t
)
ORDER BY id DESC;
優點:索引查找定位起始點,僅掃描一頁資料,**效能最佳**。
前提:ID 唯一、單調遞增(或遞減)、無大量刪除導致斷層過大。
ROW_NUMBER() 視窗函數(通用標準,SQL 2005+)SELECT TOP @PageSize *
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY id) AS rn, *
FROM table1
) t
WHERE rn > @PageSize * (@PageNum - 1);
優點:無 ID 連續性要求、支援任意排序、ANSI SQL 標準。
缺點:大偏移量需掃描並排序前 N 行,**效能最差**(全表排序 + 視窗計算)。
| 方案 | 效能 | 適用場景 | 備註 |
|---|---|---|---|
| ID 範圍 (方案二) | ⭐⭐⭐⭐⭐ | 單調 ID、高頻翻頁、大資料量 | 需動態拼接 SQL |
| NOT IN (方案一) | ⭐⭐⭐ | 小資料量、簡單原型 | 易踩 NULL 坑 |
| ROW_NUMBER (方案三) | ⭐⭐ | 無單調鍵、複雜排序、通用框架 | 大偏移考慮 Keyset 分頁 |
-- 首頁
SELECT TOP 20 * FROM table1 ORDER BY id DESC;
-- 後續頁(記住上一頁最後一筆 id = @last_id)
SELECT TOP 20 * FROM table1 WHERE id < @last_id ORDER BY id DESC;
無偏移量掃描、極致效能、適合無限滾動/APP 分頁。缺點:不支援跳頁、需客戶端記錄游標。