SQL Server 2008 R2中的高效分页

时间:2014-06-12 14:21:52

标签: sql sql-server sql-server-2008 sql-server-2008-r2 pagination

我想编写一个执行以下操作的存储过程: *返回与查询匹配的记录数(以确定显示用户的页数) *返回另一个记录集,其中包含来自当前页面查询的特定记录子集。

我在StackOverflow上发现的另一个问题(抱歉,我丢失了链接),我发现我们这样做了分页:

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

通过执行以下操作,我可以获得[淫秽长选择查询]返回的记录数量:

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

我想尽可能有效地获取这两个记录集。

我能想出如何做到这一点的唯一方法是将上述两个语句推送到一个存储过程中。由于以下几个原因,这让我觉得效率低下:

  • 我必须两次写出[淫秽的长选择查询],使解决方案更难维护/更改(如果可能,我真的想要避免这种情况)。
  • 我必须运行[淫秽的长选择查询],获取所有可能的记录(可能是数千个),然后将其缩小到合适的分页大小,只有在获得计数时再次运行它。

我尝试过的其他解决方案:

  • 在自己的存储过程中放置​​[淫秽长选择查询](这会导致语法错误)。

有什么可以做的吗?我应该把它吸干并坚持我目前的解决方案,还是有一种更优雅的方式来解决这个问题?

2 个答案:

答案 0 :(得分:1)

取决于[obscenely long select query]结构,您可以使用临时表或表变量:
- 使用匹配行的ids填充临时表 - 计算临时表行以计算页数
- 检索调用者的结果,使用与相关数据库表连接的临时表构建查询

答案 1 :(得分:0)

实施分页的一个方法是:

您的存储过程将遵循以下参数

@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)

如果你传递@PageNumbers = 1和@PageSize = 10 然后

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

同样,如果@PageNumbers = 2 然后

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

您甚至可以在SP中硬编码@PageSize值。