SQL Server query with pagination and count

前端 未结 5 1003
一生所求
一生所求 2020-12-12 13:54

I want to make a database query with pagination. So, I used a common-table expression and a ranked function to achieve this. Look at the example below.

decla         


        
相关标签:
5条回答
  • 2020-12-12 14:15

    What if you calculate the count beforehand?

    declare @pagenumber int = 2;
    declare @pagesize int = 3;
    declare @total int;
    
    SELECT @total = count(*)
    FROM @table
    
    with query as
    (
       select name, ROW_NUMBER() OVER(ORDER BY name ASC) as line from @table
    )
    select top (@pagesize) name, @total total from query
    where line > (@pagenumber - 1) * @pagesize
    

    Another way, is to calculate max(line). Check the link

    Return total records from SQL Server when using ROW_NUMBER

    UPD:

    For single query, check marc_s's answer on the link above.

        with query as
        (
           select name, ROW_NUMBER() OVER(ORDER BY name ASC) as line from @table
        )
        select top (@pagesize) name, 
           (SELECT MAX(line) FROM query) AS total 
        from query
        where line > (@pagenumber - 1) * @pagesize
    
    0 讨论(0)
  • 2020-12-12 14:17
    DECLARE @pageNumber INT = 1  , 
            @RowsPerPage INT = 20
    
    SELECT  *
    FROM    TableName
    ORDER BY Id
            OFFSET ( ( @pageNumber - 1 ) * @RowsPerPage ) ROWS
                 FETCH NEXT @RowsPerPage ROWS ONLY;
    
    0 讨论(0)
  • 2020-12-12 14:17
    @pagenumber=5
    @pagesize=5
    

    Create a common table expression and write logic like this

    Between ((@pagenumber-1)*(@pagesize))+1 and (@pagenumber *@pagesize)
    
    0 讨论(0)
  • 2020-12-12 14:19

    Assuming you are using MSSQL 2012, you can use Offset and Fetch which cleans up server-side paging greatly. We've found performance is fine, and in most cases better. As far as getting the total column count, just use the window function below inline...it will not include the limits imposed by 'offset' and 'fetch'.

    For Row_Number, you can use window functions the way you did, but I would recommend that you calculate that client side as (pagenumber*pagesize + resultsetRowNumber), so if you're on the 5th page of 10 results and on the third row you would output row 53.

    When applied to an Orders table with about 2 million orders, I found the following:

    FAST VERSION

    This ran in under a second. The nice thing about it is that you can do your filtering in the common table expression once and it applies both to the paging process and the count. When you have many predicates in the where clause, this keeps things simple.

    declare @skipRows int = 25,
            @takeRows int = 100,
            @count int = 0
    
    ;WITH Orders_cte AS (
        SELECT OrderID
        FROM dbo.Orders
    )
    
    SELECT 
        OrderID,
        tCountOrders.CountOrders AS TotalRows
    FROM Orders_cte
        CROSS JOIN (SELECT Count(*) AS CountOrders FROM Orders_cte) AS tCountOrders
    ORDER BY OrderID
    OFFSET @skipRows ROWS
    FETCH NEXT @takeRows ROWS ONLY;
    

    SLOW VERSION

    This took about 10 sec, and it was the Count(*) that caused the slowness. I'm surprised this is so slow, but I suspect it's simply calculating the total for each row. It's very clean though.

    declare @skipRows int = 25,
    @takeRows int = 100,
    @count int = 0
    
    
    SELECT 
        OrderID,
        Count(*) Over() AS TotalRows
    FROM Location.Orders
    ORDER BY OrderID
    OFFSET @skipRows ROWS
    FETCH NEXT @takeRows ROWS ONLY;
    

    CONCLUSION

    We've gone through this performance tuning process before and actually found that it depended on the query, predicates used, and indexes involved. For instance, the second we introduced a view it chugged, so we actually query off the base table and then join up the view (which includes the base table) and it actually performs very well.

    I would suggest having a couple of straight-forward strategies and applying them to high-value queries that are chugging.

    0 讨论(0)
  • 2020-12-12 14:21

    There are many way we can achieve pagination: I hope this information is useful to you and others.

    Example 1: using offset-fetch next clause. introduce in 2005

    declare @table table (name varchar(30));
    insert into @table values ('Jeanna Hackman');
    insert into @table values ('Han Fackler');
    insert into @table values ('Tiera Wetherbee');
    insert into @table values ('Hilario Mccray');
    insert into @table values ('Mariela Edinger');
    insert into @table values ('Darla Tremble');
    insert into @table values ('Mammie Cicero');
    insert into @table values ('Raisa Harbour');
    insert into @table values ('Nicholas Blass');
    insert into @table values ('Heather Hayashi');
    
    declare @pagenumber int = 1
    declare @pagesize int = 3
    
    --this is a CTE( common table expression and this is introduce in 2005)
    with query as
    (
      select ROW_NUMBER() OVER(ORDER BY name ASC) as line, name from @table
    ) 
    
    --order by clause is required to use offset-fetch
    select * from query
    order by name 
    offset ((@pagenumber - 1) * @pagesize) rows
    fetch next @pagesize rows only
    

    Example 2: using row_number() function and between

    declare @table table (name varchar(30));
    insert into @table values ('Jeanna Hackman');
    insert into @table values ('Han Fackler');
    insert into @table values ('Tiera Wetherbee');
    insert into @table values ('Hilario Mccray');
    insert into @table values ('Mariela Edinger');
    insert into @table values ('Darla Tremble');
    insert into @table values ('Mammie Cicero');
    insert into @table values ('Raisa Harbour');
    insert into @table values ('Nicholas Blass');
    insert into @table values ('Heather Hayashi');
    
    declare @pagenumber int = 2
    declare @pagesize int = 3
    
    SELECT *
    FROM 
    (select ROW_NUMBER() OVER (ORDER BY PRODUCTNAME) AS RowNum, * from Products)
    as Prodcut
    where RowNum between (((@pagenumber - 1) * @pageSize )+ 1) 
    and (@pagenumber * @pageSize )
    

    I hope these will be helpful to all

    0 讨论(0)
提交回复
热议问题