在SQL Server中分页结果的最佳方法是什么
时间:2020-03-06 14:29:31 来源:igfitidea点击:
如果我们还希望获得结果总数(在进行分页之前),那么在SQL Server 2000、2005、2008、2012中对结果进行分页的最佳方法(从性能角度而言)是什么?
解决方案
我们没有指定语言,也没有指定使用哪个驱动程序。因此,我正在抽象地描述它。
- 创建一个可滚动的结果集/数据集。这要求在桌子上有一个主桌子
- 跳到最后
- 请求行数
- 跳到页面的开始
- 滚动浏览各行,直到页面末尾
获取结果总数和分页是两个不同的操作。为了这个示例,我们假设我们要处理的查询是
SELECT * FROM Orders WHERE OrderDate >= '1980-01-01' ORDER BY OrderDate
在这种情况下,我们可以使用以下方法确定结果总数:
SELECT COUNT(*) FROM Orders WHERE OrderDate >= '1980-01-01'
...这看似效率低下,但实际上假设所有索引等均已正确设置,性能相当不错。
接下来,要以分页的方式获取实际结果,以下查询将是最有效的:
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
这将返回原始查询的第1-19行。这里最酷的事情是,尤其是对于Web应用程序,我们无需保留任何状态,除了要返回的行号。
在http://www.codeproject.com/KB/aspnet/PagingLarge.aspx上可以很好地概述不同的分页技术。
我在SQL Server 2000中经常使用ROWCOUNT方法(与ROW_NUMBER相比也可以在2005&2008中使用),闪电般快速,但是我们需要确保已排序的列(主要是)的唯一值。
好吧,我在SQL 2000数据库中使用了以下示例查询,它也适用于SQL 2005. 通过使用多列,它为我们提供的功能是动态排序的。
我告诉你...这很强大:)
ALTER PROCEDURE [dbo].[RE_ListingReports_SelectSummary]
@CompanyID int,
@pageNumber int,
@pageSize int,
@sort varchar(200)
AS
DECLARE @sql nvarchar(4000)
DECLARE @strPageSize nvarchar(20)
DECLARE @strSkippedRows nvarchar(20)
DECLARE @strFields nvarchar(4000)
DECLARE @strFilter nvarchar(4000)
DECLARE @sortBy nvarchar(4000)
DECLARE @strFrom nvarchar(4000)
DECLARE @strID nvarchar(100)
If(@pageNumber < 0)
SET @pageNumber = 1
SET @strPageSize = CAST(@pageSize AS varchar(20))
SET @strSkippedRows = CAST(((@pageNumber - 1) * @pageSize) AS varchar(20))-- For example if pageNumber is 5 pageSize is 10, then SkippedRows = 40.
SET @strID = 'ListingDbID'
SET @strFields = 'ListingDbID,
ListingID,
[ExtraRoom]
'
SET @strFrom = ' vwListingSummary '
SET @strFilter = ' WHERE
CompanyID = ' + CAST(@CompanyID As varchar(20))
End
SET @sortBy = ''
if(len(ltrim(rtrim(@sort))) > 0)
SET @sortBy = ' Order By ' + @sort
-- Total Rows Count
SET @sql = 'SELECT Count(' + @strID + ') FROM ' + @strFROM + @strFilter
EXEC sp_executesql @sql
--// This technique is used in a Single Table pagination
SET @sql = 'SELECT ' + @strFields + ' FROM ' + @strFROM +
' WHERE ' + @strID + ' IN ' +
' (SELECT TOP ' + @strPageSize + ' ' + @strID + ' FROM ' + @strFROM + @strFilter +
' AND ' + @strID + ' NOT IN ' + '
(SELECT TOP ' + @strSkippedRows + ' ' + @strID + ' FROM ' + @strFROM + @strFilter + @SortBy + ') '
+ @SortBy + ') ' + @SortBy
Print @sql
EXEC sp_executesql @sql
最好的部分是sp_executesql缓存以后的调用,前提是我们传递相同的参数,即生成相同的sql文本。

