Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 选择子查询的计数(*),但不运行两次_Sql_Sql Server_Tsql_Count_Paging - Fatal编程技术网

Sql 选择子查询的计数(*),但不运行两次

Sql 选择子查询的计数(*),但不运行两次,sql,sql-server,tsql,count,paging,Sql,Sql Server,Tsql,Count,Paging,我有一个程序返回一个结果集,这个结果集受页码和其他内容的限制。作为一个输出参数,我需要根据参数(页码除外)返回所选行的总数。所以我有这样的想法: 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 Positio

我有一个程序返回一个结果集,这个结果集受页码和其他内容的限制。作为一个输出参数,我需要根据参数(页码除外)返回所选行的总数。所以我有这样的想法:

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
然后我需要将输出参数设置为innerquery中的行数。我可以复制查询并对其进行计数,但此查询可能会返回数千行(将来还会返回更多行),因此我正在寻找性能良好的方法。我在考虑表变量,这是个好主意吗?还有其他建议吗

更具体地说,是MicrosoftSQLServer2008


谢谢你,简

我想你应该在单独的查询中完成。虽然这两个查询看起来几乎相同,但查询优化器处理它们的方式会有很大的不同


从理论上讲,SQL Server甚至可能无法遍历子查询中的所有行以进行计数。

我现在无法访问我的代码库,但我相信可以使用count()OVER(或类似命令)返回子查询中的总行数。然后可以将其作为最终结果集的一部分返回。它在每一行中都会被复制,但在我看来,对于使用分页的应用程序来说,这只是一个小的性能损失,而且最终的结果应该是有限的

再过几个小时,我会发布准确的代码

编辑:这是我用来生成计数的行。最后,我们的开发人员需要一个单独的方法来获取计数,所以现在我在同一个存储过程中的两个位置维护搜索条件

COUNT(*) OVER (PARTITION BY '') AS TotalCount

将其添加到CTE中,然后您可以选择TotalCount,它将成为您每行中的一列。

您可以使用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)将执行时间增加了一倍。

您不能将输出变量设置为@RowCount吗?这将获取受上次执行语句影响的行:

SELECT stuff FROM mytable

SET @output = @@ROWCOUNT

这将为您提供所需的内容,而不需要再次运行查询。

您必须在不限制范围的情况下至少运行整个查询一次,才能获得完整的行计数。由于您仍要执行此操作,因此应选择@RowCount以输出找到的总行数,而不是在每行中使用冗余的count(*)列重载数据读取器

1.首次运行新查询时: 2.仅读取前X行 上述查询避免了使用冗余计数(*)列淹没SqlDataReader,否则每次调用SqlDataReader.Read()都会发送该列由于您是第一次运行查询。。。不要选择范围,只需读取前X行。这将为您提供所需的内容。。。完整结果计数、第一个X记录和结果集的高效流式处理,无需冗余计数列

3.用于同一查询的后续运行,以获取结果的子集
在任何情况下,
@@rowcount
都是在第一次运行查询时访问计数的最直接的方法,无需限制结果集(您仍然需要第一个X结果),无需运行单独的count()查询,无需使用临时表,也无需包含冗余的count()列。

+1表示count(*)over()但不会计数(1) over()会更好吗?这在性能方面没有什么区别,SQL在内部将count()更改为与count(1)相同的值。MySql也是这样,它将count()转换为count(0)。虽然count(1)的键入速度更快!恐怕不会,但这将给出所选页面中的记录数,而不是集合中的总记录数。
select YOUR_COLUMNS 
from YOUR_TABLE 
where YOUR_SEARCH_CONDITION 
order by YOUR_COLUMN_ORDERING_LIST;
select @@rowcount;
select YOUR_COLUMNS 
from (select YOUR_COLUMNS, ROW_NUMBER() 
over(order by BY YOUR_COLUMN_ORDERING_LIST) as RowNum) Results 
where Results.RowNum between @From and @To;