首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQL Server 分頁查詢:ROW_NUMBER() 過濾任意頁範圍數據

     編輯:關於SqlServer

核心語法:ROW_NUMBER() 窗口函數分頁

適用於 SQL Server 2005+,標準、高效、支持任意頁碼跳轉。

DECLARE @PageSize INT = 10,   -- 每頁條數
        @PageIndex INT = 4;   -- 當前頁碼 (從 1 開始)

SELECT * 
FROM (
    SELECT 
        t.*,
        ROW_NUMBER() OVER (ORDER BY Id DESC) AS RowNum  -- 排序欄位按業務調整
    FROM YourTable t
) AS PagedData
WHERE RowNum BETWEEN (@PageIndex - 1) * @PageSize + 1 
                 AND @PageIndex * @PageSize
ORDER BY RowNum;

關鍵點解析

元素說明
ROW_NUMBER() OVER (ORDER BY ...)為結果集按指定排序生成連續行號 (從 1 開始)。
子查詢別名 (PagedData)窗口函數結果必須在外層引用,不能直接在 WHERE 中使用。
BETWEEN 範圍計算第 N 頁 = (N-1)*Size+1 到 N*Size。例:第 4 頁、每頁 10 條 → 31-40。
外層 ORDER BY RowNum保證最終輸出順序與分頁邏輯一致。

替代方案:TOP + NOT IN (舊版/簡單場景)

-- 缺點:性能隨頁碼增大急劇下降,不推薦大數據量深分頁
SELECT TOP 10 * 
FROM UserInfo 
WHERE Id NOT IN (
    SELECT TOP 30 Id FROM UserInfo ORDER BY Id  -- 跳過前 3 頁 (3*10)
)
ORDER BY Id;

SQL Server 2012+ 新語法:OFFSET FETCH (最簡潔)

SELECT * 
FROM YourTable
ORDER BY Id DESC
OFFSET (@PageIndex - 1) * @PageSize ROWS  -- 跳過前 N 行
FETCH NEXT @PageSize ROWS ONLY;           -- 取後 M 行
  • 語法簡潔,執行計劃優化更好,推薦 2012+ 環境優先使用。
  • 需配合 ORDER BY 使用。

性能對比與選型建議

方案適用版本深分頁性能代碼複雜度推薦指數
ROW_NUMBER()2005+良好 (需覆蓋索引支持)中等⭐⭐⭐⭐
OFFSET FETCH2012+優秀 (優化器原生支持)低⭐⭐⭐⭐⭐
TOP + NOT IN2000+極差 (隨頁碼線性惡化)低⭐ (僅小數據/教學)
游標/臨時表所有可控但開發維護成本高高⭐⭐ (特殊業務)

索引優化關鍵

分頁查詢性能核心在於 ORDER BY 列上有合適索引:

  • 單表:在排序列上建立非聚集索引 (含覆蓋查詢列)。
  • 聯表:按 JOIN/WHERE/Order By 列建立複合索引。
  • 避免在大表上無索引排序 + 深分頁,會導致大量邏輯讀與排序溢出到 tempdb。

完整可運行示例 (AdventureWorks 風格)

-- 創建測試表
CREATE TABLE dbo.TestPaging (
    Id INT IDENTITY(1,1) PRIMARY KEY,
    Name VARCHAR(50),
    CreateTime DATETIME DEFAULT GETDATE()
);
INSERT INTO dbo.TestPaging (Name) 
SELECT TOP 1000 'Item_' + CAST(ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS VARCHAR)
FROM sys.objects a, sys.objects b;

-- 分頁存儲過程
CREATE PROCEDURE dbo.sp_GetPagedData
    @PageIndex INT = 1,
    @PageSize INT = 20,
    @TotalCount INT OUTPUT
AS
BEGIN
    SET NOCOUNT ON;
    
    SELECT @TotalCount = COUNT(*) FROM dbo.TestPaging;
    
    SELECT Id, Name, CreateTime
    FROM (
        SELECT *, ROW_NUMBER() OVER (ORDER BY Id DESC) AS RowNum
        FROM dbo.TestPaging
    ) t
    WHERE RowNum BETWEEN (@PageIndex - 1) * @PageSize + 1 AND @PageIndex * @PageSize
    ORDER BY RowNum;
END
GO

-- 測試調用
DECLARE @Total INT;
EXEC dbo.sp_GetPagedData @PageIndex = 3, @PageSize = 10, @TotalCount = @Total OUTPUT;
PRINT '總記錄數: ' + CAST(@Total AS VARCHAR);
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved