What is the best way to paginate results in SQL Server

前端 未结 19 2469
我寻月下人不归
我寻月下人不归 2020-11-22 01:36

What is the best way (performance wise) to paginate results in SQL Server 2000, 2005, 2008, 2012 if you also want to get the total number of results (before paginating)?

相关标签:
19条回答
  • 2020-11-22 02:04

    From SQL Server 2012, we can use OFFSET and FETCH NEXT Clause to achieve the pagination.

    Try this, for SQL Server:

    In the SQL Server 2012 a new feature was added in the ORDER BY clause, to query optimization of a set data, making work easier with data paging for anyone who writes in T-SQL as well for the entire Execution Plan in SQL Server.

    Below the T-SQL script with the same logic used in the previous example.

    --CREATING A PAGING WITH OFFSET and FETCH clauses IN "SQL SERVER 2012"
    DECLARE @PageNumber AS INT, @RowspPage AS INT
    SET @PageNumber = 2
    SET @RowspPage = 10 
    SELECT ID_EXAMPLE, NM_EXAMPLE, DT_CREATE
    FROM TB_EXAMPLE
    ORDER BY ID_EXAMPLE
    OFFSET ((@PageNumber - 1) * @RowspPage) ROWS
    FETCH NEXT @RowspPage ROWS ONLY;
    

    TechNet: Paging a Query with SQL Server

    0 讨论(0)
  • 2020-11-22 02:05

    Finally, Microsoft SQL Server 2012 was released, I really like its simplicity for a pagination, you don't have to use complex queries like answered here.

    For getting the next 10 rows just run this query:

    SELECT * FROM TableName ORDER BY id OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;
    

    https://docs.microsoft.com/en-us/sql/t-sql/queries/select-order-by-clause-transact-sql#using-offset-and-fetch-to-limit-the-rows-returned

    Key points to consider when using it:

    • ORDER BY is mandatory to use OFFSET ... FETCH clause.
    • OFFSET clause is mandatory with FETCH. You cannot use ORDER BY ... FETCH.
    • TOP cannot be combined with OFFSET and FETCH in the same query expression.
    0 讨论(0)
  • 2020-11-22 02:06

    Incredibly, no other answer has mentioned the fastest way to do pagination in all SQL Server versions. Offsets can be terribly slow for large page numbers as is benchmarked here. There is an entirely different, much faster way to perform pagination in SQL. This is often called the "seek method" or "keyset pagination" as described in this blog post here.

    SELECT TOP 10 first_name, last_name, score, COUNT(*) OVER()
    FROM players
    WHERE (score < @previousScore)
       OR (score = @previousScore AND player_id < @previousPlayerId)
    ORDER BY score DESC, player_id DESC
    

    The "seek predicate"

    The @previousScore and @previousPlayerId values are the respective values of the last record from the previous page. This allows you to fetch the "next" page. If the ORDER BY direction is ASC, simply use > instead.

    With the above method, you cannot immediately jump to page 4 without having first fetched the previous 40 records. But often, you do not want to jump that far anyway. Instead, you get a much faster query that might be able to fetch data in constant time, depending on your indexing. Plus, your pages remain "stable", no matter if the underlying data changes (e.g. on page 1, while you're on page 4).

    This is the best way to implement pagination when lazy loading more data in web applications, for instance.

    Note, the "seek method" is also called keyset pagination.

    Total records before pagination

    The COUNT(*) OVER() window function will help you count the number of total records "before pagination". If you're using SQL Server 2000, you will have to resort to two queries for the COUNT(*).

    0 讨论(0)
  • 2020-11-22 02:06

    From 2012 onward we can use OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY

    0 讨论(0)
  • 2020-11-22 02:06

    For the ROW_NUMBER technique, if you do not have a sorting column to use, you can use the CURRENT_TIMESTAMP as follows:

    SELECT TOP 20 
        col1,
        col2,
        col3,
        col4
    FROM (
        SELECT 
             tbl.col1 AS col1
            ,tbl.col2 AS col2
            ,tbl.col3 AS col3
            ,tbl.col4 AS col4
            ,ROW_NUMBER() OVER (
                ORDER BY CURRENT_TIMESTAMP
                ) AS sort_row
        FROM dbo.MyTable tbl
        ) AS query
    WHERE query.sort_row > 10
    ORDER BY query.sort_row
    

    This has worked well for me for searches over table sizes of even up to 700,000.

    This fetches records 11 to 30.

    0 讨论(0)
  • You didn't specify the language nor which driver you are using. Therefore I'm describing it abstractly.

    • Create a scrollable resultset / dataset. This required a primary on the table(s)
    • jump to the end
    • request the row count
    • jump to the start of the page
    • scroll through the rows until the end of the page
    0 讨论(0)
提交回复
热议问题