如何在SELECT T-SQL命令的结果集中包含返回行的总数?

如何在SELECT T-SQL命令的结果集中包含返回行的总数?,sql,sql-server,tsql,Sql,Sql Server,Tsql,我想问一下,是否有一种方法可以同时使用Row\u number命令将总行数作为附加列包含在TSQL查询返回的结果集中 例如,以类似以下的形式获取对Book表的查询的结果集: RowNum BookId BookTitle TotalRows -------------------------------------------- 1 1056 Title1 5 2 1467 Title2 5

我想问一下,是否有一种方法可以同时使用
Row\u number
命令将总行数作为附加列包含在TSQL查询返回的结果集中

例如,以类似以下的形式获取对Book表的查询的结果集:

RowNum   BookId     BookTitle    TotalRows
--------------------------------------------
1        1056       Title1       5    
2        1467       Title2       5    
3        121        Title3       5    
4        1789       Title4       5    
5        789        Title5       5

查询是存储过程中实现的自定义分页功能的一部分。我们的目标是仅返回当前页面索引的记录,并限制为页面大小,还返回select语句中的记录总数,以确定结果集页面的总数。

也许您要查找的是?

可以使用CTE执行此操作:

WITH result AS (SELECT ... your query here ...)
SELECT
    *,
    (SELECT COUNT(*) FROM result) AS TotalRows
FROM result;

一般来说,我不建议这样做,但如果您真的需要,那么这就是如何做到的。

使用AdventureWorks数据库的示例

select 
    *, 
    TotalVolume = (select COUNT(*) from HumanResources.Department) 
from  HumanResources.Department
注意@@ROWCOUNT提供上一个命令中的行数。运行以下命令:

SELECT    1 AS n;

SELECT  n ,
        @@ROWCOUNT
FROM    ( SELECT    1 AS n
          UNION ALL
          SELECT    2 AS n
        ) AS t

通过对问题的评论,很明显这个问题与分页有关。在这种情况下,有两种广泛的方法:

  • 查询与搜索条件匹配的所有行(而不仅仅是一页),并将其存储到表值变量中(以及行号)。然后对该表值变量运行两个查询:一个用于提取所需的数据页,另一个用于获取总计数
  • 不要使用表值变量,只需运行完整查询两次,一次获取数据页,一次获取总计数
  • 如果行的总数是以千为单位度量的,那么第一个选项工作得很好。如果总数要高得多,最好运行两次查询

    这是一个典型的空间/处理权衡


    你的相似性可能会有所不同——在一种情况下效果好的东西在另一种情况下可能会很糟糕

    在SQL Server 2008及更高版本中,添加
    COUNT(*)
    OVER()
    作为查询中的一个列名,该列名将填充返回的总行数

    它在每一行中重复,但至少该值可用

    许多其他解决方案不起作用的原因是,对于非常大的结果集,在迭代所有行之前,您不会知道总数,这在许多情况下是不实际的(尤其是顺序处理解决方案)。例如,此技术提供调用第一个
    IDataReader.Read()
    后的总计数

    select COUNT(*) OVER () as Total_Rows, ... from ...
    


    此查询是否由应用程序发出?如果是这样,您就不能计算应用程序中返回的行数吗?这会更有效率。以后发布代码时请不要使用制表符-这会弄脏格式。@OMGPonies,我不是说返回整个表,只是返回本来应该返回的行,事实上,它们将返回少一列,这样数据就更少了@OMG Ponies:不,如果将TotalRows列添加到查询中,并为每行发送一次总行计数值,则数据集将更大。如果只发送数据集并对应用程序中的行进行计数,则可以避免重复总行数。冗余数据=传输速度较慢(这很糟糕)。@OMG Ponies:True如果您不需要所有行,那么每行发送计数的数据会更少,单独发送计数的数据会更少。但从提供的示例来看,他似乎想要返回的行数。我认为这会产生一个错误,如
    列'ColumnA'在选择列表中无效,因为它既不包含在聚合函数中,也不包含在GROUP BY子句中。
    Chaps我在经过一个极端的反复之后编辑了这篇文章。有时我甚至会惊讶于自己:-)是有效的,但对于更复杂的查询,您将在两个位置重复相同的FROM/JOIN/WHERE等。您可以识别自己的错误。这就是课堂,你为什么反对?如果他必须得到结果中的行,那么在得到结果之后,他仍然必须再次运行查询,以获得记录的总数。重复这么多次并不理想。您可以在之后使用
    @@rowcount
    ,或者在应用程序中计算计数。这确实应该被接受为答案。4年后,这确实帮助我解决了问题。这是迄今为止最好的答案。行得通,但我现在的查询速度慢了三倍。我不认为还有其他方法可以实现这一点。有吗?如果他必须得到结果中的行,他在得到结果后仍然必须再次运行查询,以获得记录的总数。使用方法#2,如何避免重复从和选择查询的整个部分两次?当连接和筛选非常复杂时,这可能会导致严重的代码重复。@julealgon将代码的公共位放入视图中可以避免代码重复。但这通常不会给您提供准确的计数。连接其他表可能会使结果大为混乱。请注意,这可能会在查询执行计划中使用段运算符(在本例中,它意味着计算每行的计数),这将大大降低查询速度。。
    SELECT    1 AS n;
    
    SELECT  n ,
            @@ROWCOUNT
    FROM    ( SELECT    1 AS n
              UNION ALL
              SELECT    2 AS n
            ) AS t
    
    select COUNT(*) OVER () as Total_Rows, ... from ...