1. 程式人生 > >What is the best way to paginate results in SQL Server

What is the best way to paginate results in SQL Server

先了解 MySQL server side paging:

First off, don’t have a separate server script for each page, that is just madness. Most applications implement pagination via use of a pagination parameter in the URL. Something like:

http://yoursite.com/itempage.php?page=2

You can access the requested page number via $_GET['page']

.

This makes your SQL formulation really easy:

// determine page number from $_GET
$page = 1;
if(!empty($_GET['page'])) {
    $page = filter_input(INPUT_GET, 'page', FILTER_VALIDATE_INT);
    if(false === $page) {
        $page = 1;
    }
}

// set the number of items to display per page
$items_per_page 
= 4; // build query $offset = ($page - 1) * $items_per_page; $sql = "SELECT * FROM menuitem LIMIT " . $offset . "," . $items_per_page;

So for example if input here was page=2, with 4 rows per page, your query would be”

SELECT * FROM menuitem LIMIT 4,4

So that is the basic problem of pagination. Now, you have the added requirement that you want to understand the total number of pages (so that you can determine if “NEXT PAGE” should be shown or if you wanted to allow direct access to page X via a link).

對應到 MSSQL, 解法有分

SQL Server 2005, 2008, 2012, 2014… if you also want to get the total number of results (before paginating)?

2012 之後的版本:

I was also very curious about why Microsoft doesn’t support simple queries with offset/limit like in MySQL or PostgreSQL. Finally, released Microsoft SQL Server 2012, I really like its simplicity for 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;

Key points to consider when using it:

  • ORDER BY is mandatory to use OFFSET and FETCH clause.
  • OFFSET clause is mandatory with FETCH. You can never use, ORDER BY … FETCH.
  • TOP cannot be combined with OFFSET and FETCH in the same query expression.

for 2005 / 2008:

Getting the total number of results and paginating are two different operations. For the sake of this example, let’s assume that the query you’re dealing with is

SELECT * FROM Orders WHERE OrderDate >= '1980-01-01' ORDER BY OrderDate

In this case, you would determine the total number of results using:

SELECT COUNT(*) FROM Orders WHERE OrderDate >= '1980-01-01'

…which may seem inefficient, but is actually pretty performant, assuming all indexes etc. are properly set up.

Next, to get actual results back in a paged fashion, the following query would be most efficient:

SELECT  *
FROM    ( SELECT    ROW_NUMBER() OVER ( ORDER BY OrderDate ) AS RowNum, *
          FROM      Orders
          WHERE     OrderDate >= '1980-01-01'
        ) AS RowConstrainedResult
WHERE   RowNum >= 1
    AND RowNum < 20
ORDER BY RowNum

This will return rows 1-19 of the original query. The cool thing here, especially for web apps, is that you don’t have to keep any state, except the row numbers to be returned.

資料來源: