Sql server T-SQL在应用TOP之前获取行计数

Sql server T-SQL在应用TOP之前获取行计数,sql-server,tsql,select,Sql Server,Tsql,Select,我有一个SELECT,它可以从一个表返回数百行,表可以是~50000行。我的应用程序很想知道返回的行数,这对我来说很重要,但实际上它只使用了数百行中的前5行。我想做的是限制SELECT查询只返回5行,同时告诉我的应用程序它将返回多少行。这是原始查询: SELECT id, a, b, c FROM table WHERE a < 2 你能想出更好的办法吗 T-SQl中是否有方法在应用top之前返回select top查询受影响的行数@@rowcount将返回5,但我想知道是否有@rowc

我有一个SELECT,它可以从一个表返回数百行,表可以是~50000行。我的应用程序很想知道返回的行数,这对我来说很重要,但实际上它只使用了数百行中的前5行。我想做的是限制SELECT查询只返回5行,同时告诉我的应用程序它将返回多少行。这是原始查询:

SELECT id, a, b, c FROM table WHERE a < 2
你能想出更好的办法吗

T-SQl中是否有方法在应用top之前返回select top查询受影响的行数@@rowcount将返回5,但我想知道是否有@rowcountbeforetop之类的东西

提前感谢你的帮助

**更新**

这就是我现在正在做的,我有点喜欢CTE,尽管CTE如此优雅

-- @count is passed in as an out param to the stored procedure

CREATE TABLE dbo.#everything (id int, a int, b int, c int);

INSERT INTO #everything 
SELECT id, a, b, c FROM table WHERE a < 2;      

SET @count = @@rowcount;
SELECT TOP (5) id FROM #everything;
DROP TABLE #everything; 

假设您希望按id升序排列前5名,则只需通过表一次即可

; WITH Everything AS 
(
    SELECT id
        , a
        , b
        , c
        , ROW_NUMBER() OVER (ORDER BY id ASC) AS rn_asc
        , ROW_NUMBER() OVER (ORDER BY id DESC) AS rn_desc
    FROM <table>
)
SELECT id
    , a
    , b
    , c
    , rn_asc + rn_desc - 1 AS total_rows
FROM Everything
WHERE rn_asc <= 5

这里有一个相对有效的方法来获取5个随机行并包括总计数。随机元素将引入完整排序,无论您将其放置在何处

SELECT TOP (5) id,a,b,c,total = COUNT(*) OVER()
  FROM dbo.mytable
  ORDER BY NEWID();
**更新**

这就是我现在正在做的,我有点喜欢CTE,尽管CTE如此优雅。让我知道你的想法。谢谢

-- @count is passed in as an out param to the stored procedure

CREATE TABLE dbo.#everything (id int, a int, b int, c int);

INSERT INTO #everything 
SELECT id, a, b, c FROM table WHERE a < 2;      

SET @count = @@rowcount;
SELECT TOP (5) id FROM #everything;
DROP TABLE #everything; 

执行两个查询有什么问题?一个带有SELECT COUNT*和一个带有TOP?您不应该使用没有ORDER子句的TOP。你是如何定义TOP的?@DeCaf不错,但看起来很多余,你不觉得吗?特别是当选择最终增长为多个联接或条件时。但是,是的,这将以冗余代码为代价满足我的要求。@NickVaccaro很好的观察,在这种情况下,我只想要一个随机的5,排序对应用程序没有多大意义。没有排序的TOP不会给你随机数…你可以通过使用COUNT*Overhanks更有效、更不冗长地完成这项工作,但结果与我目前得到的结果相似,总共5行显示了总行。@sOltan那么,您希望总行显示在哪里?作为一个不同的结果集?如果是这样,那么只需运行一个单独的查询!这太好了!但它仍然将每一行中的计数作为一列包含在内,而且当我尝试使用它时,它在一个名为“worktable”的对象上生成了大量逻辑读取。请看我对原始帖子的更新,我倾向于将计数与前5名分开。Thanks@sOltan这些额外的读取是否真的会导致明显的性能问题?你似乎对自己的目标很困惑。我认为您需要决定是否关心计数是否包含在结果的每一行中。没有简单的方法可以只包含一次,也不能避免工作表中的东西,我怀疑这是由于随机顺序,而不是计数-也许你也应该将这两个需求分开。没有明显的性能问题,你的查询非常棒,我已经记下了。现在,我将行数作为out参数返回,我在下面发布了一个更新。非常感谢您的帮助,如果您对我的更新有任何反馈,我将不胜感激。我使用Server2008R2进行了一些测试,与单独运行top和count查询相比,我的加速速度提高了2倍,但它非常不可靠,而且通常会降低10倍。很遗憾MSSQL不支持游标。三年后仍然有用!使用上面的方法来加速红移Postgres查询-谢谢!为什么需要临时表?您认为插入到新对象并获取@@ROWCOUNT比只从基表中选择COUNT*便宜吗?同样,如果你想要的是随机的话,TOP without ORDER BY也不会给你随机的。随机和未定义之间有很大区别。就我个人而言,我不喜欢输出参数。我认为它们太容易被忽略,并且返回第二个带有单个值的表更干净。然而,这是我的观点,来自于考虑应用层外观的人。我更喜欢看到C或其他处理2个数据表的集合。祝你好运!除了扫描整个表并将其插入临时表之外,您的意思是没有额外的开销?为什么你认为这不涉及任何开销?听起来你有足够的建议来完成这项工作。所有这些都不会比其他任何一个明显好或坏,所以这一切都取决于你。我建议选择你的答案,然后结束这个问题。如果您还有更多问题,请分别提出。好的,顺便说一句,扫描与原始问题中不存在的WHERE子句匹配的整个索引范围!。为什么你认为临时表在内存中?我认为你对效率不高和效率不低的含义的理解有很大的偏差。
-- @count is passed in as an out param to the stored procedure

CREATE TABLE dbo.#everything (id int, a int, b int, c int);

INSERT INTO #everything 
SELECT id, a, b, c FROM table WHERE a < 2;      

SET @count = @@rowcount;
SELECT TOP (5) id FROM #everything;
DROP TABLE #everything;