如果你想知道COUNT(*)
> 0然后您可以使用EXISTS
来提高查询效率。当我想知道COUNT(*)
>时,我是否有办法提高查询效率? 1?
(需要与SQL Server和Oracle兼容。)
谢谢,杰米
编辑:
我正在尝试提高某些代码的性能。有一些类似于:
if (SQL('SELECT COUNT(*) FROM table WHERE a = b') > 0) then...
和
if (SQL('SELECT COUNT(*) FROM table WHERE a = b') > 1) then...
第一行很容易切换到EXISTS
语句,但是我可以使第二行更有效吗?从评论和我自己的想法,我有以下的想法,他们中的任何一个会更有效吗?
if (SQLRecordCount('SELECT TOP 2 1 FROM table WHERE a = b') > 1) then...
(我可以将ROWNUM
用于Oracle。)
if (SQL('SELECT 1 FROM table WHERE a = b HAVING COUNT(*) > 1') = 1) then...
以下在SQL Server中不起作用:
SELECT COUNT(*) FROM (SELECT TOP 2 FROM table WHERE a = b)
但这与Oracle有关:
SELECT COUNT(*) FROM (SELECT 1 FROM table WHERE a = b AND ROWNUM < 3)
到目前为止,感谢您的帮助。
答案 0 :(得分:1)
这样的事情可行:
select myDate
from myTable
where myColumn = myCondition
group by myDate
having count(*) > 1
虽然如果我有你的确切查询或合理的传真,我可以帮助你更多。
就实际的关键字效率而言,据我所知,关于它的SQL程序员并不多。这将是你的RDBMS如何处理实际计数的函数。如果它看到它将返回该行,如果有2次发生并且停止计数为2,那么很好。如果它不够智能并且跟踪另外1000次出现,那就不那么好了。
如果您在连接或子查询中使用它,则可以控制在查询或存储过程中的各个点返回的行数。您可以越早过滤掉永远不会返回的行,就越好。
答案 1 :(得分:1)
目前你的问题有点抽象。你能提供更多的背景吗?
我在想,如果你在foo, id
上有一个综合索引,那么下面的索引可以通过两次索引搜索得到满足。
SELECT CASE WHEN MAX(id)= MIN(id) THEN 0 ELSE 1 END
FROM yourtable
WHERE foo='bar'
或许可以更明确地强制计划
SELECT CASE WHEN COUNT(*) = 2 THEN 1 ELSE 0 END FROM
(
SELECT MAX(id)
FROM yourtable
WHERE foo='bar'
UNION
SELECT MIN(id)
FROM yourtable
WHERE foo='bar'
) AS T
答案 2 :(得分:1)
如果索引
,那应该没那么重要示例:
200万行表,相当宽,900MB磁盘,虚拟SQL Server 2005。
这提供了17,876行
SELECT COUNT(*), ThingID FROM dbo.TwoMillion IT GROUP BY ThingID HAVING COUNT(*) > 1
|--Filter(WHERE:([Expr1002]>(1)))
|--Compute Scalar(DEFINE:([Expr1002]=CONVERT_IMPLICIT(int,[Expr1005],0)))
|--Hash Match(Aggregate, HASH:([IT].[ThingID]) DEFINE:([Expr1005]=COUNT(*)))
|--Index Scan(OBJECT:([MyDB].[dbo].[TwoMillion].[IX_Thing] AS [IT]))
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0
Table 'TwoMillion'. Scan count 1, logical reads 8973, physical reads 3, read-ahead reads 8969... all zeroes
第二次运行
Table 'Worktable'. = same
Table 'TwoMillion'. Scan count 1, logical reads 8973, ... all zeroes
CPU time = 453 ms, elapsed time = 564 ms.
答案 3 :(得分:0)
完全忽略SQL Server中的交叉兼容性要求,您可以使用TOP
显式限制扫描的行数。在某些情况下,这可能是有益的,如下面(有点人为的)例子。
USE tempdb
CREATE TABLE Orders
(
OrderId INT IDENTITY(1,1) PRIMARY KEY,
Blah VARCHAR(10)
)
INSERT INTO Orders
SELECT TOP 10 LEFT(name,10)
FROM sys.objects
CREATE TABLE OrderItems
(
OrderItemId INT IDENTITY(1,1) PRIMARY KEY,
OrderId INT REFERENCES Orders(OrderId)
)
CREATE NONCLUSTERED INDEX ix ON OrderItems(OrderId)
INSERT INTO OrderItems (OrderId)
SELECT TOP 1000000 1+ ROW_NUMBER() OVER (ORDER BY (SELECT 0))% 10
FROM sys.all_columns c1, sys.all_columns c2
SET STATISTICS IO ON
SET STATISTICS TIME ON
SELECT o.OrderId, o.Blah
FROM Orders o JOIN OrderItems oi ON o.OrderId = oi.OrderId
GROUP BY o.OrderId, o.Blah
HAVING COUNT(*) > 1
/*
Table 'Orders'. Scan count 0, logical reads 20
Table 'OrderItems'. Scan count 1, logical reads 1742
*/
SELECT o.OrderId, o.Blah
FROM Orders o
CROSS APPLY
(SELECT TOP 2 OrderItemId FROM
OrderItems oi WHERE o.OrderId = oi.OrderId) CA
GROUP BY o.OrderId, o.Blah
HAVING COUNT(*) > 1
/*
Table 'OrderItems'. Scan count 10, logical reads 30
Table 'Orders'. Scan count 1, logical reads 2
*/
DROP TABLE OrderItems
DROP TABLE Orders
答案 4 :(得分:0)
我发现以下行显着改善了SQL Server的性能,在我的测试中从大约40ms到大约5ms。
SELECT COUNT(*) FROM (SELECT TOP 2 1 AS x FROM table Where a = b) AS y
注意别名,它们是使查询起作用所必需的。
不幸的是,以下查询似乎没有提高Oracle的性能:
SELECT COUNT(*) FROM table WHERE a = b AND ROWNUM < 3
答案 5 :(得分:-1)
首先,如果要优化查询,则不应使用星号。
也许最好创建一个带限制的查询?你对伯爵或类似的东西不感兴趣。您只想知道是否有多个条目:
select id
from mytable
where ...
limit 2
这应该非常快。比调用countRows给你,以获得你需要的答案。