2010-12-14 48 views
1

我有一个应该只返回前10个结果非常大的查询:查询的总行数的

从选择排名前10位的ProductId .....

的问题是,我也希望与没有“前10位”的条件匹配的结果总数,但同时返回所有行(我们正在谈论大约10万条结果)的结果是不合适的。

有没有办法获得受前一个查询影响的行的总数,无论是在其中还是在后续的查询中,都没有再次运行它?

PS:请100个000行:))

回答

4

没有临时表倾倒在一个变量的数量和返回

​​
+0

这有效地运行查询两次 - 一次获得计数,一次获得前10个结果。有没有办法避免运行两次?它的执行时间为几秒 – 2010-12-14 13:01:04

+0

没有,如果你想要的总行数,但100000行不是很多行,是非常广泛的表,更重要的是你的where子句由索引覆盖..也是你在计数查询中不需要ORDER BY – SQLMenace 2010-12-14 13:04:32

+0

它是一个宽表,它执行大量连接和大量过滤。我担心它会尽可能优化。我只是希望不要两次运行它 – 2010-12-14 13:08:09

0

我想你可以为联合攻击它选择

select top 10 ... from ... where ... 
union 
select count(*) from ... where ... 

为了避免这种类型的黑客攻击,您需要向计数查询添加虚假列,以便返回与主查询相同数量的列。例如:

select top 10 id, first_name from people 
union 
select count(*), '' as first_name from people 

我不推荐使用此解决方案。使用两个单独的查询是如何应该做

+0

我不确定这是否不会执行查询两次 – 2010-12-14 13:15:42

+0

返回的结果集将因为您正在添加的第11行而改变。 – SnatchFrigate 2010-12-14 13:28:39

+0

从本质上讲,它确实运行了两个查询,你不能在一个查询中做你想要做的事情,最终在你的应用程序中你可以运行两个查询或者运行一个同样的事情。 我不确定union是否可以在oracle之外使用。这只会让您选择运行两个单独的查询。 – SnatchFrigate 2010-12-14 13:36:59

0

一般来说没有 - 推理如下:

如果查询规划可利用的TOP 10只返回10行,然后(!) RDBMS甚至不知道满足全部条件的确切行数,它只是获得TOP 10。

因此,当您想要找出满足条件的所有行的计数时,您没有运行第二次,但第一次。

说了适当的索引可能会使两个查询执行相当快。

编辑
MySQL有SQL_CALC_FOUND_ROWS返回,如果有应用无极限的查询将返回的行数 - 谷歌搜索在MS SQL点分析SQL和CTE变等效,看到this forum(即使不确定要么有资格运行它只有一次,但随时检查 - 并让我们知道)。

2

假设您已经使用了ORDER BY子句(以正确定义哪些“TOP 10”结果),那么您还可以添加ROW_NUMBER的调用,并使用相反的排序顺序,并选择最高值回。

例如,以下内容:

select top 10 *,ROW_NUMBER() OVER (order by id desc) from sysobjects order by ID 

拥有2001个值,2000年,1999年等一最后一栏,降。以下内容:

select COUNT(*) from sysobjects 

确认sysobjects中有2001行。

+1

这是一个很好的解决方案,但你也可以使用COUNT而不是ROW_NUMBER,所以你不必两次订购表格。 从sysobjects中选择top 10 *,COUNT(*)OVER()ID – Lamak 2010-12-14 14:01:14

+0

@Lamak - 如果您愿意,您可以自己添加该答案。我总是忘记'COUNT(*)OVER()' – 2010-12-14 14:05:05

+0

是的,我相信你的回答是正确的,它应该被接受,这就是为什么我没有发布我的,它的基本相同。 – Lamak 2010-12-14 14:08:38