2016-11-23 28 views
0

我正在使用SQL Server 2012.我需要在存儲過程中進行分頁。在客戶端(網頁),我需要存儲過程的結果爲請求的頁面,並且我需要有行數而不考慮用於設置該條件頁數的頁碼。分頁數據並獲得行計數不考慮存儲過程中的頁碼

例如,我需要運行這個存儲過程查詢第二頁十行的時候,我是的SubscribeID 12345674.

Create Procedure TestSelectBill 
    (@PageNumber int = 1 , 
    @RowCount int = 10 , 
    @SubscribeId Int = 0) 
As 
Begin 
    Select * 
    From billing.BillMaster As BM 
    Where (Bm.SubscribeId = @SubscribeId) 
    Order by SubscribeId 
     Offset (@PageNumber - 1) * @RowCount Rows 
     Fetch Next @RowCount Rows Only; 
End 

我必須執行這樣這個存儲過程:

Execute TestSelectBill 
     @PageNumber = 2, @RowCount int = 10, @SubscribeId = 12345674 

想象一下,我有billing.BillMaster 105行這SubscribeId = 123456574。現在我需要向最終用戶顯示10行,因此我必須讓他選擇1到11之間的一個頁面。

這意味着我需要知道有多少行存在此條件SubscribeId = 123456574

我可以改變,如下面的代碼我的存儲過程返回的行數:

Create Procedure TestSelectBill 
    (@PageNumber int = 1, 
    @RowCount int = 10, 
    @SubscribeId Int = 0) 
As 
Begin 
    DECLARE @ROW_COUNT INT = 0 

    -- Find Row Count for this condition 
    Select 
     @ROW_COUNT = COUNT(*) 
    From 
     billing.BillMaster As BM 
    Where 
     (Bm.SubscribeId = @SubscribeId) 

    -- Select Result 
    SELECT 
     Row_Count = @ROW_COUNT,  
     * 
    FROM 
     billing.BillMaster As BM 
    WHERE 
     (Bm.SubscribeId = @SubscribeId) 
    ORDER BY 
     SubscribeId 
     OFFSET (@PageNumber - 1) * @RowCount ROWS 
     FETCH NEXT @RowCount ROWS ONLY; 
End 

但是當你看到我寫我選擇兩次,這是不好的,因爲存儲的這種修改和維護程序將非常複雜。

而且,我能救我的結果到臨時表中,然後使用類似下面的代碼:

CREATE Procedure TestSelectBill 
    (@PageNumber int = 1, 
    @RowCount int = 10, 
    @SubscribeId Int = 0) 
As 
Begin 
    DECLARE @ROW_COUNT INT = 0 

    -- Main Select 
    SELECT      
     * 
    FROM 
     billing.BillMaster As BM 
    INTO 
     #T 
    WHERE 
     (Bm.SubscribeId = @SubscribeId) 

    -- Find Row Count for this condituion 
    SELECT @ROW_COUNT = COUNT(*) 
    FROM #T 

    -- Select Result 
    SELECT 
     Row_Count = @ROW_COUNT, 
     * 
    FROM 
     #T 
    ORDER BY 
     SubscribeId 
     OFFSET (@PageNumber - 1) * @RowCount ROWS 
     FETCH NEXT @RowCount ROWS ONLY; 
End 

但你可以這樣看,我使用物理臨時表,可以很慢當我有很多的數據在主要選擇與外面尋呼。

任何人都可以告訴我最好的方法嗎?

回答

1

-- First solution use count with window function 
CREATE Procedure TestSelectBill 
    (@PageNumber int = 1, 
    @RowCount int = 10, 
    @SubscribeId Int = 0) 
As 
Begin 
    SELECT 
     COUNT(*) OVER(ORDER BY (SELECT NULL)) AS row_count , 
     * 
    FROM 
     billing.BillMaster As BM 
    WHERE 
     (Bm.SubscribeId = @SubscribeId) 
    ORDER BY 
     SubscribeId 
     OFFSET (@PageNumber - 1) * @RowCount ROWS 
     FETCH NEXT @RowCount ROWS ONLY; 
End 
GO 


-- Second solution: use dynamic sql with multiple result 
Create Procedure TestSelectBill 
    @PageNumber int = 1, 
    @RowCount int = 10, 
    @SubscribeId Int = 0 
As 
Begin 

    DECLARE @params NVARCHAR(max) = '@PageNumber int, @RowCount int, @SubscribeId int' 
    DECLARE @where NVARCHAR(max) = N' WHERE Bm.SubscribeId = @SubscribeId' 
    DECLARE @stmt NVARCHAR(max) = N'SELECT COUNT(*) as row_cnt FROM billing.BillMaster As BM ' 
    DECLARE @stmt_rowcount NVARCHAR(max) = N'SELECT * FROM billing.BillMaster As BM ' 
    DECLARE @order_by NVARCHAR(max) = ' ORDER BY SubscribeId 
     OFFSET (@PageNumber - 1) * @RowCount ROWS 
     FETCH NEXT @RowCount ROWS ONLY;' 

    SET @stmt += @where + @order_by 
    SET @stmt_rowcount += @where 

    -- First result set (rowcount) 
    EXEC [sys].[sp_executesql] 
     @stmt = @stmt_rowcount, 
     @params = @params, 
     @SubscribeId = @SubscribeId, 
     @PageNumber = @PageNumber, 
     @RowCount = @RowCount 


    -- Second result set (data) 
    IF @@ERROR = 0 
    BEGIN 
     EXEC [sys].[sp_executesql] 
      @stmt = @stmt, 
      @params = @params, 
      @SubscribeId = @SubscribeId, 
      @PageNumber = @PageNumber, 
      @RowCount = @RowCount 

    END 

End 
GO 


 
+0

您的第一個解決方案對我有好處。謝謝 –

0

您可以創建一個臨時表,其中標識列的每個插入的行增加1,然後讀取該列的最大值以獲取行數。