Efficient pagination in SQL Server 2008 R2

僤鯓⒐⒋嵵緔 提交于 2019-12-10 23:46:03

问题


I want to write a stored procedure that does the following: * Returns the number of records matching a query (to determine the number of pages to show the user) * Returns another recordset with a certain subset of records from a query for the current page.

From another question I found on StackOverflow (sorry, I lost the link), I found that we do pagination like this:

SELECT u.* FROM 
(
    SELECT t.*, ROW_NUMBER() OVER (ORDER BY t.id) as rownum FROM
    (
        [obscenely long select query]
    )
    as t
)
AS u WHERE u.rowNum >= 1 AND u.rowNum <= 20

And I can get the number of records returned by [obscenely long select query] by doing the following:

SELECT COUNT(*) AS numRecords from ([obscenely long select query]) AS records

I want to get both of these recordsets as effectively as possible.

The only way I can figure how to do it is shoving both of those statements above into one stored procedure. This strikes me as inefficient for a few reasons:

  • I have to write out [obscenely long select query] twice, making the solution harder to maintain / change (I really want to avoid this, if possible).
  • I have to run [obscenely long select query], getting all the possible records (which could be thousands) before cutting it down to a reasonable size for the pagination, only to run it again when getting the count.

Other solutions I've tried:

  • Putting [obscenely long select query] in its own stored procedure (this causes syntax errors).

Is there anything that can be done? Should I just suck it up and stick with my current solution, or is there a more elegant way to pull this off?


回答1:


depending on the [obscenely long select query] structure you may be able to use a temp table or table variable:
- fill a temp table with the ids of the matching rows
- count the temp table rows to calculate the number of pages
- to retrieve the results for the caller build a query with the temp table joined with the relevant database tables




回答2:


One soluntion for implementing pagination is:

Your stored procedure will following parameters

@PageSize INT,
@PageNumbers INT

;WITH CTE AS(
        SELECT a,
               b,
                ROW_NUMBER() OVER(ORDER BY a) RN
        FROM    TableName
)
SELECT  *
FROM    CTE
WHERE   RN  BETWEEN ((@PageNumbers - 1) * @PageSize + 1) AND (@PageNumbers * @PageSize)

If you pass @PageNumbers = 1 and @PageSize = 10 Then

((@PageNumbers - 1) * @PageSize + 1) = ((1 - 1) * 10 + 1) = 1
and (@PageNumbers * @PageSize) = (1 * 10) = 10

Similarly, if @PageNumbers = 2 Then

((@PageNumbers - 1) * @PageSize + 1) = ((2 - 1) * 10 + 1) = 11
and (@PageNumbers * @PageSize) = (2 * 10) = 20

You can even hard code @PageSize value in your SP.



来源:https://stackoverflow.com/questions/24186804/efficient-pagination-in-sql-server-2008-r2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!