SQLServer 2000中高效的分页(限制)查询?
-
20-08-2019 - |
题
在 SQLServer 2000 中进行分页查询最有效的方法是什么?
其中“分页查询”相当于在 MySQL 中使用 LIMIT 语句。
编辑:在这种情况下,存储过程是否比任何基于集合的查询更有效?
解决方案
大型结果集的寻呼和获胜者是使用行数。也有对更复杂的查询的通用版本。 但给予信贷雅斯曼·米尔莫维奇:)
DECLARE @Sort /* the type of the sorting column */
SET ROWCOUNT @StartRow
SELECT @Sort = SortColumn FROM Table ORDER BY SortColumn
SET ROWCOUNT @PageSize
SELECT ... FROM Table WHERE SortColumn >= @Sort ORDER BY SortColumn
本文包含了整个的源代码。
请阅读“更新2004-05-05”的信息。 !
其他提示
我觉得嵌套SELECT TOP n
查询可能是完成它的最有效方式。
SELECT TOP ThisPageRecordCount *
FROM Table
WHERE ID NOT IN (SELECT TOP BeforeThisPageRecordCount ID FROM Table ORDER BY OrderingColumn)
ORDER BY OrderingColumn
替换ThisPageRecordCount
每页和BeforeThisPageRecordCount
项与(PageNumber - 1) * items-per-page
。
当然,在SQL Server 2005的更好的办法是使用ROW_NUMBER()
功能的CTE。
查询的效率实际上取决于底层表是如何构成的。如果说你有一个名为ID主键是一个身份,和的它是一个聚集索引的和的你可以假设,没有人被它做IDENTITY_INSERTs,你可以做像的查询:
SELECT TOP XXX FROM表WHERE ID> @LastPagesID;
这将让你的结果尽可能快。否则那将是真正有效的一切都是这方面的一些变种 - 也许它不是一个ID - 也许你正在使用的页面什么是真正的你知道是唯一的一个日期,但你明白了吧...的IN()基于此处显示将可能工作的查询,但它们不会接触的部分聚集或覆盖索引扫描的性能。
我认为您真正拥有的是升级到 SQL 2005 的令人信服的理由。
在 SQL 2005 中,可以通过以下方式快速轻松地完成此操作:
select ROW_NUMBER() over (order by [MyField]) as rowNum, *
from [MyTable]
where rowNum between @firstRow and @lastRow
如果您真的坚持使用 SQL 2000,我会担心 - 微软不会再完全支持它太久了,因为它现在已经是两代之前的了。
恐怕没有一种最好的方法可以做到这一点 - 所有解决方案都有点黑客。
然而,@Petar Petrov 的答案可能是最一致的:
- 如果您正在处理较小表上的聚集索引进行排序,那么 ASC-DESC 方法(使用 TOP 每种方式动态构建两种排序)可能会更快。
- 如果您的数据相对静态并且排序是固定的,那么您可以添加自己的 rowNum 字段,在更改排序顺序时更新该字段(听起来很糟糕,但对于大型表来说会很快)。
我认为您每次都会花几个小时使用查询分析器进行调整。无论哪种方式,存储过程都不会产生太大区别 - 查询计划的缓存不太可能成为瓶颈。
这是将任何表执行分页一个通用的SQL Server 2000的存储过程。所存储的过程接受表中的名称,所述列输出(默认为表中的所有列),可选的WHERE条件,可选的排序顺序,页号来检索和每页的行数。
CREATE PROCEDURE [dbo].[GetPage]
@pTableName VARCHAR(30),
@pColumns VARCHAR(200) = '*',
@pFilter VARCHAR(200) = '',
@pSort VARCHAR(200) = '',
@pPage INT = 1,
@pPageRows INT = 10
AS
SET NOCOUNT ON
DECLARE @vSQL VARCHAR(4000)
DECLARE @vTempTable VARCHAR(30)
DECLARE @vRowStart INT
DECLARE @vTotalRows INT
SET @vTempTable = '##Tmp' + CAST(DATEPART(YYYY, GETDATE()) AS VARCHAR(4)) +
CAST(DATEPART(MM, GETDATE()) AS VARCHAR(2)) +
CAST(DATEPART(DD, GETDATE()) AS VARCHAR(2)) +
CAST(DATEPART(HH, GETDATE()) AS VARCHAR(2)) +
CAST(DATEPART(MI, GETDATE()) AS VARCHAR(2)) +
CAST(DATEPART(SS, GETDATE()) AS VARCHAR(2)) +
CAST(DATEPART(MS, GETDATE()) AS VARCHAR(3))
SET @vSQL = 'SELECT ' + @pColumns + ', IDENTITY(INT, 1, 1) AS ROWID INTO ' + @vTempTable + ' FROM ' + @pTableName
IF @pFilter != '' AND @pFilter IS NOT NULL
SET @vSQL = @vSQL + ' WHERE ' + @pFilter
IF @pSort != '' AND @pSort IS NOT NULL
SET @vSQL = @vSQL + ' ORDER BY ' + @pSort
EXECUTE (@vSQL)
-- Get the total number of rows selected
SET @vTotalRows = @@ROWCOUNT
-- If page number = 0, set it to the first page
IF @pPage = 0
SET @pPage = 1
-- If page number is beyond the last page, set page to the last page
IF (@pPage * @pPageRows) > @vTotalRows
BEGIN
SET @pPage = @vTotalRows / @pPageRows
IF (@vTotalRows % @pPageRows) != 0
SET @pPage = @pPage + 1
END
SET @vRowStart = ((@pPage - 1) * @pPageRows) + 1
SET @vSQL = 'SELECT * FROM ' + @vTempTable + ' WHERE ROWID BETWEEN ' + CAST(@vRowStart AS VARCHAR(10)) +
' AND ' + CAST((@vRowStart + @pPageRows - 1) AS VARCHAR(10)) + ' ORDER BY ROWID'
EXECUTE (@vSQL)
SET @vSQL = 'DROP TABLE ' + @vTempTable
EXECUTE (@vSQL)
GO
下面是关于如何使用Northwing数据库使用它的几个例子:
EXECUTE [dbo].[GetPage] 'Customers', '*', '', '', 1, 10
EXECUTE [dbo].[GetPage] 'Customers', '*', '', 'CustomerID DESC', 1, 10
要确认,这不是我的工作,但礼貌 http://www.eggheadcafe.com/PrintSearchContent.asp?LINKID=1055
干杯,约翰