我可以从sql server中的一个sql查询中获取count()和行吗?

我可以从sql server中的一个sql查询中获取count()和行吗?,sql,sql-server,tsql,aggregate,Sql,Sql Server,Tsql,Aggregate,我想得到某个查询的结果总数和前n行-可能吗 在一份声明中 我预计结果如下: count(..) column1 column2 125 some_value some_value 125 some_value some_value 提前谢谢你 您可以通过交叉连接和CTE来实现这一点,但效率不高: WITH Rows_CTE AS ( SELECT Column1, Column2 FROM Table WHERE (

我想得到某个查询的结果总数和前n行-可能吗 在一份声明中

我预计结果如下:

count(..) column1        column2
125         some_value   some_value
125         some_value   some_value
提前谢谢你

您可以通过
交叉连接
和CTE来实现这一点,但效率不高:

WITH Rows_CTE AS
(
    SELECT Column1, Column2
    FROM Table
    WHERE (...)
)
SELECT c.Cnt, r.Column1, r.Column2
FROM Rows_CTE r
CROSS JOIN (SELECT COUNT(*) AS Cnt FROM Rows_CTE) c
我认为获得所需内容的更好方法是使用单个查询但多个结果集,这可以通过使用
COMPUTE

SELECT Column1, Column2
FROM Table
WHERE (...)
COMPUTE COUNT([Column1])
像这样:

SELECT TOP 100 --optional
    MC.Cnt, M.Column1, M.Column2
FROM
    myTable M
    CROSS JOIN
    (SELECT COUNT(*) AS Cnt FROM myTable) MC
编辑:在向下投票和计数/超过答案后。我国两种表格的比较

您可以看到我的交叉连接/简单聚合和COUNT/空orderby子句之间的巨大差异

SELECT COUNT(*) OVER() AS C, key1col, key2col
FROM myTable

(24717 row(s) affected)

Table 'Worktable'. Scan count 3, logical reads 49865, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'myTable'. Scan count 1, logical reads 77, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

StmtText
  |--Nested Loops(Inner Join)
       |--Table Spool
       |    |--Segment
       |         |--Index Scan(OBJECT:([MyDB].[dbo].[myTable].[IX_useful]))
       |--Nested Loops(Inner Join, WHERE:((1)))
            |--Compute Scalar(DEFINE:([Expr1003]=CONVERT_IMPLICIT(int,[Expr1005],0)))
            |    |--Stream Aggregate(DEFINE:([Expr1005]=Count(*)))
            |         |--Table Spool
            |--Table Spool

SELECT
    MC.Cnt, M.key1col, M.key2col
FROM
    myTable M
    CROSS JOIN
    (SELECT COUNT(*) AS Cnt FROM myTable) MC

(24717 row(s) affected)

Table 'myTable'. Scan count 2, logical reads 154, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.


StmtText
  |--Nested Loops(Inner Join)
       |--Compute Scalar(DEFINE:([Expr1005]=CONVERT_IMPLICIT(int,[Expr1009],0)))
       |    |--Stream Aggregate(DEFINE:([Expr1009]=Count(*)))
       |         |--Index Scan(OBJECT:([MyDB].[dbo].[myTable].[IX_useful]))
       |--Index Scan(OBJECT:([MyDB].[dbo].[myTable].[IX_useful] AS [M]))
我在一个有57000行的表上重复了这一点,这是IO

Table 'Worktable'. Scan count 3, logical reads 1535456, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'myTable'. Scan count 1, logical reads 2929, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.


Table 'myTable'. Scan count 34, logical reads 6438, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
那怎么办

SELECT COUNT(*) OVER() AS C, COLUMN1, COLUMN2
FROM TABLE  
关于
交叉连接
查询
在繁重的
INSERT
/
DELETE
环境中,交叉联接将返回不正确的行计数

从多个连接尝试此操作
连接1

set nocount on;
drop table dbo.test_table;
GO
create table dbo.test_table
(
    id_field uniqueidentifier not null default(newid()),
    filler char(2000) not null default('a')
);
GO
create unique clustered index idx_id_fld on dbo.test_table(id_field);
GO
while 1 = 1
insert into dbo.test_table default values;
连接2

select T2.cnt, T1.id_field, T1.filler
from dbo.test_table T1
cross join (select COUNT(*) as cnt from dbo.test_table) T2

select T2.cnt, T1.id_field, T1.filler
from dbo.test_table T1
cross join (select COUNT(*) as cnt from dbo.test_table) T2

select T2.cnt, T1.id_field, T1.filler
from dbo.test_table T1
cross join (select COUNT(*) as cnt from dbo.test_table) T2
每次记录的计数(
@@ROWCOUNT
)都不同于
T2.cnt

如果
COUNT(*)OVER()
,则只有一次表扫描,
@@ROWCOUNT
始终与
T2.cnt

关于查询计划-SQL 2005 SP3在()上执行
COUNT(*)的能力似乎比SQL 2008 R2弱得多。除此之外,它还错误地报告了查询成本(我从未想过子查询的成本会超过整个查询的100%)

在许多情况下,
COUNT(*)OVER()
的成本在
交叉连接的50-75%之间

交叉连接的最佳情况是使用非常窄的索引进行计数。这样,将对数据进行聚集索引扫描+对计数进行索引扫描


和往常一样,最好是衡量、衡量、衡量并接受你乐于接受的妥协。

尝试一下这个问题:

select ColumnId,Descr,(select COUNT(*) from ColumnSetUp)as c
from ColumnSetUp
group by ColumnId,Descr

为什么要使用CTE?对派生表进行简单的交叉连接即可。而且COMPUTE也不推荐使用。@gbn:我确实使用了
交叉连接。CTE是这样的,谓词可以重用(注意包含
WHERE(…)
,这在问题中缺失,但可能包含在生产环境中)。我知道
COMPUTE
在技术上是不受欢迎的,但是
ROLLUP
不能在这里取代它,使用
COMPUTE
可以从计划中删除整个表/索引扫描。坦率地说,他们不赞成
COMPUTE
,这让我很恼火,因为它仍然是在没有
GROUPBY
子句的情况下计算聚合的唯一方法。但这是另一天的咆哮。我也喜欢计算机。该死的有用。我打算建议相同的(ish)方法,比连接好得多,只使用一次扫描。这是首选方法。你有没有将性能与我的方法进行比较?像狗一样跑。它必须在一个工作台上增加计数+1才能把你所有的枪都拔出来。我得看看我的执行计划。@Chris Bednarski:我以前被咬过!还可以将统计时间设置为si有用:CPU为x5到x10,持续时间为x2,用于me@gbn:我现在有兴趣看看2005年和2008年之间的表现是否有很大差异。在2005年,它像狗一样跑。@Chris Bednarski:请让我们知道:早些时候与我的同事谈论这件事。顺便说一下,在逻辑阅读方面,这两个数字是不可直接比较的。是的,可能。请参考下面的链接。