当前位置:  开发笔记 > 数据库 > 正文

选择子查询的COUNT(*)而不运行它两次

如何解决《选择子查询的COUNT(*)而不运行它两次》经验,为你挑选了1个好方法。

我有一个程序来返回一个受页码和其他东西限制的结果集.作为OUTPUT参数,我需要根据除页码之外的参数返回所选行的总量.所以我有类似的东西:

WITH SelectedItems AS
(SELECT Id, Row1, Row2, ROW_NUMBER() OVER (ORDER BY Row1) AS Position
FROM Items
WHERE Row2 = @Row2)
SELECT Id, Row1, Row2
FROM SelectedItems
WHERE Position BETWEEN @From AND @To

然后我需要将OUTPUT参数设置为内部查询中的行数.我可以复制查询并对其进行计数,但是这个查询可能会返回数千行(并且将来会更多),所以我正在寻找方法来实现这一点并获得良好的性能.我在考虑表变量,这是个好主意吗?还是其他任何建议?

更具体地说,它是Microsoft SQL Server 2008.

谢谢你,Jan



1> badbod99..:

您可以使用COUNT(*)将总行数计入主查询中的单独列.像这样:

WITH SelectedItems AS
(SELECT Id, Row1, Row2, ROW_NUMBER() OVER (ORDER BY Row1) AS Position, 
COUNT(*) OVER () AS TotalRows
FROM Items
WHERE Row2 = @Row2)
SELECT Id, Row1, Row2
FROM SelectedItems
WHERE Position BETWEEN @From AND @To

这将返回结果集中的计数而不是输出参数,但这应该符合您的要求.否则,与临时表结合使用:

DECLARE @tmp TABLE (Id int, RowNum int, TotalRows int);

WITH SelectedItems AS
(SELECT Id, Row1, Row2, ROW_NUMBER() OVER (ORDER BY Row1) AS Position, 
COUNT(*) OVER () AS TotalRows
FROM Items
WHERE Row2 = @Row2)
INSERT @tmp
SELECT Id, Row1, Row2
FROM SelectedItems
WHERE Position BETWEEN @From AND @To

SELECT TOP 1 @TotalRows = TotalRows FROM @tmp
SELECT * FROM @tmp

您会发现使用临时表只是为了您的分页结果不会占用太多内存(当然,这取决于您的页面大小),并且您只能在短时间内保持活动状态.从临时表中选择完整的结果集并选择TotalRows只需要更长的时间.

这将比运行完全独立的查询快得多,在我的测试中(重复WITH)将执行时间加倍.


它在性能方面没有区别,SQL内部将count(*)更改为count(1).在MySql中也是如此,它将count(*)转换为count(0).虽然count(1)更快输入!
推荐阅读
跟我搞对象吧
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有