MySQL 支援 LIMIT m, n 跳過 m 筆取 n 筆,但 SQL Server (2005/2008/R2/2012 早期版本) 無此語法,需用 TOP 結合子查詢實現。
-- 取第 7-9 筆 (跳過 6 筆,取 3 筆)
SELECT TOP 3 id FROM tablename
WHERE id NOT IN (
SELECT TOP 6 id FROM tablename
)
缺點:大資料量時 NOT IN 效能差,且需確保 id 唯一且有索引。
-- 取第 m+1 到 n 筆 (頁碼從 1 開始,每頁 pageSize 筆)
-- 參數:@pageSize=每頁筆數, @pageIndex=頁碼(1-based)
DECLARE @offset INT = (@pageIndex - 1) * @pageSize;
SELECT TOP (@pageSize) id FROM tablename
WHERE id NOT IN (
SELECT TOP (@offset) id FROM tablename ORDER BY id
)
ORDER BY id;
WITH Numbered AS (
SELECT id, ROW_NUMBER() OVER (ORDER BY id) AS rn
FROM tablename
)
SELECT id FROM Numbered
WHERE rn BETWEEN @offset + 1 AND @offset + @pageSize;
優點:語法清晰、效能穩定、支援複雜排序與分組。
SELECT id FROM tablename
ORDER BY id
OFFSET @offset ROWS
FETCH NEXT @pageSize ROWS ONLY;
最佳選擇:語法最接近 MySQL LIMIT,執行計畫最優化。
| 方案 | 適用版本 | 效能 | 維護性 | 推薦度 |
|---|---|---|---|---|
| NOT IN | 2000+ | 差 (大資料) | 中 | ★☆☆☆☆ |
| 雙重 TOP | 2005+ | 中 | 中 | ★★☆☆☆ |
| ROW_NUMBER | 2005+ | 良 | 良 | ★★★★☆ |
| OFFSET FETCH | 2012+ | 最佳 | 最佳 | ★★★★★ |
CREATE PROCEDURE usp_PageQuery
@pageIndex INT = 1,
@pageSize INT = 20,
@totalCount INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
-- 取得總筆數
SELECT @totalCount = COUNT(*) FROM tablename;
-- 計算偏移量
DECLARE @offset INT = (@pageIndex - 1) * @pageSize;
-- 分頁查詢 (使用 ROW_NUMBER)
WITH Numbered AS (
SELECT *, ROW_NUMBER() OVER (ORDER BY id) AS rn
FROM tablename
)
SELECT * FROM Numbered
WHERE rn BETWEEN @offset + 1 AND @offset + @pageSize;
END