Sql Server TOP - 如何使用?

5

在SQL Server中有没有关键字或元信息可以告诉你TOP是否生效?

EX:
Select TOP 5 * From Stuff

RESULT: 5 rows

什么是确定是否存在6个或更多的最佳方法?
I could do:
SELECT TOP 6 count(*) FROM Stuff

但我对另外一个获取计数的调用有所担忧,因为实际查询比这个复杂得多,并且在大型表上运行。

谢谢!


"生效"是指以何种方式?这意味着它实际上限制了您的结果集吗?只需计算您收到的内容。 - bluevector
@jonnyGold 计算他得到的内容并不能告诉他是否有比他要求的更多的行可用。 - ean5533
1
没有使用 ORDER BYTOP 是毫无意义的 - 你会得到按照什么顺序排列的 TOP 行?! - marc_s
2
@jonnyGold,我认为他的问题很清楚。他正在运行一个使用“TOP xxx”查询,并想知道是否有一种方法可以确定该“TOP”子句是否实际限制了结果集。 (即,如果他的查询恰好返回5行,或者有更多行但“TOP”将其限制) - ean5533
1
@marc_s 我认为这并不是他问题的重点 - 这只是一个虚拟查询,用来说明他的观点。有一个 ORDER BY 不会影响他所问的内容。 - ean5533
显示剩余2条评论
6个回答

12

没有可以自动使用的东西。你可以使用类似以下内容的东西:

DECLARE @N INT = 5;

WITH T
     AS (SELECT TOP (@N + 1) *
         FROM   master..spt_values
         ORDER  BY number)
SELECT TOP (@N) *,
             CASE
               WHEN Count(*) OVER () = (@N + 1) THEN 1
               ELSE 0
             END AS MoreRecords
FROM   T
ORDER  BY number 

3
不,因为他的WITH只选择了6行。 - ean5533
@ean5533 对的,但是原帖中的 WITH 可能不行。我可能会使用一个变量来演示这一点。 - Aaron Bertrand
@AaronBertrand - OP 应该有一个 TOP 6(或 TOP N+1),这样它就可以在扫描到第六行后停止扫描。 - Martin Smith
@aaron。我口误了。临时结果集。这样会影响性能吗? - LethalFlipper
@LethalFlipper - 说实话,我认为Carl的答案会更有效率。它避免了SQL Server需要在计划中添加一个spool的需求。 - Martin Smith
显示剩余5条评论

7

好的,你可以在客户端代码中选择前N+1个元素(在你的例子中N为5,所以在你的例子中选择前6个元素),并且丢弃最后一个元素,使用第六个元素的存在来确定如果一开始使用N是否会产生影响。然而,我不确定这样做有多少价值。


哇,今天真是漫长的一天。不确定为什么我没想到这个。 - LethalFlipper
更新/详细信息:因为我想在服务器上配置实际的最大结果大小,所以我将@N作为输出参数返回给客户端。这使得客户端可以将@N与结果计数进行比较,并在需要时显示消息。由于客户端的分布式特性,这也使得修补变得更加容易。 - LethalFlipper

0

您可以在查询中添加一个布尔值,当具有相同逻辑的子查询的 COUNT(*) 返回大于5的值时,返回 true,当它返回5或更小的值时返回 false。

这将向返回的数据中添加您需要的信息。如果您担心性能,并且查询非常复杂,则与单独查询相比可能不会有很大的改善,但至少应该能提供一些小的改进。


0

如果不进行两个查询或者执行性能损耗重计算,那么没有办法实现这一点...

Select TOP 5 * From Stuff

并且

Select Count(*) From Stuff

1
不是这样的,COUNT() OVER() 可以做到这一点。 - Aaron Bertrand
@AaronBertrand 我想查看查询计划,以确定哪种方式更有效。 - bluevector
1
随意。迄今为止提出的所有解决方案中,当我将所有解决方案一起执行时,Carl 和 Martin 的解决方案各占总成本的 4%。RedFilter 的解决方案要高出1%,达到5%,HLGEM 的解决方案为42%,而您的建议与其他解决方案组合后为44%。我是在对 sys.all_columns 进行测试。 - Aaron Bertrand

0
SELECT TOP 5 Field1, field2, recordcount 
FROM Stuff
CROSS JOIN  (SELECT  COUNT(*) as recordcount FROM Stuff) a
ORDER BY Field1

请注意,我已删除了使用SELECT *和在获取TOP N记录时不使用ORDER BY的SQL反模式。 - HLGEM

0
select top 5 *,
    case when count(*) OVER() <= 5 then 'yes' else 'no' end as AllRecordsReturned
from supportContacts

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接