在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应用程序,你不需要保留任何状态,除了要返回的行号。
其他回答
试试这个方法:
SELECT TOP @offset a.*
FROM (select top @limit b.*, COUNT(*) OVER() totalrows
from TABLENAME b order by id asc) a
ORDER BY id desc;
http://www.codeproject.com/KB/aspnet/PagingLarge.aspx上有关于不同分页技术的很好的概述
我经常在SQL Server 2000中使用ROWCOUNT方法(也可以在2005和2008中使用,只测量与ROW_NUMBER相比的性能),它的速度非常快,但你需要确保排序的列(大多数)具有唯一的值。
这个位使您能够使用SQL Server和新版本的MySQL进行分页,并携带每行中的总行数。 使用您的类推键来计数唯一行数。
WITH T AS
(
SELECT TABLE_ID, ROW_NUMBER() OVER (ORDER BY TABLE_ID) AS RN
, (SELECT COUNT(TABLE_ID) FROM TABLE) AS TOTAL
FROM TABLE (NOLOCK)
)
SELECT T2.FIELD1, T2.FIELD2, T2.FIELD3, T.TOTAL
FROM TABLE T2 (NOLOCK)
INNER JOIN T ON T2.TABLE_ID=T.TABLE_ID
WHERE T.RN >= 100
AND T.RN < 200
这是2012年老SO问题的重复: 实现分页的有效方法
从[TableX] ORDER BY [FieldX] 偏移量500行 只获取下100行
这里将更详细地讨论这个主题,并使用替代方法。
用例方面,以下内容似乎易于使用和快速。只需设置页码。
use AdventureWorks
DECLARE @RowsPerPage INT = 10, @PageNumber INT = 6;
with result as(
SELECT SalesOrderDetailID, SalesOrderID, ProductID,
ROW_NUMBER() OVER (ORDER BY SalesOrderDetailID) AS RowNum
FROM Sales.SalesOrderDetail
where 1=1
)
select SalesOrderDetailID, SalesOrderID, ProductID from result
WHERE result.RowNum BETWEEN ((@PageNumber-1)*@RowsPerPage)+1
AND @RowsPerPage*(@PageNumber)
同样没有CTE
use AdventureWorks
DECLARE @RowsPerPage INT = 10, @PageNumber INT = 6
SELECT SalesOrderDetailID, SalesOrderID, ProductID
FROM (
SELECT SalesOrderDetailID, SalesOrderID, ProductID,
ROW_NUMBER() OVER (ORDER BY SalesOrderDetailID) AS RowNum
FROM Sales.SalesOrderDetail
where 1=1
) AS SOD
WHERE SOD.RowNum BETWEEN ((@PageNumber-1)*@RowsPerPage)+1
AND @RowsPerPage*(@PageNumber)
推荐文章
- 如何为查询返回的每一行执行存储过程一次?
- 按IN值列表排序
- 为什么引入无用的MOV指令会加速x86_64汇编中的紧循环?
- 如何使用SQL Server 2008做多个CASE WHEN条件?
- 计数在VARCHAR字段中字符串的出现次数?
- 如何选择多行填充常量?
- 修改一个MySQL列为AUTO_INCREMENT
- 如果没有使用EXISTS引入子查询,则只能在选择列表中指定一个表达式
- SQL Server -事务回滚错误?
- 如何在SQL中有效地计数列值的发生?
- 查询以列出数据库中每个表中的记录数量
- PostgreSQL列名区分大小写吗?
- 使用curl在PHP中获取HTTP代码
- 在WHERE子句中引用列别名
- 存储图像在SQL Server?