下面哪个查询更快?

不存在:

SELECT ProductID, ProductName 
FROM Northwind..Products p
WHERE NOT EXISTS (
    SELECT 1 
    FROM Northwind..[Order Details] od 
    WHERE p.ProductId = od.ProductId)

或不在:

SELECT ProductID, ProductName 
FROM Northwind..Products p
WHERE p.ProductID NOT IN (
    SELECT ProductID 
    FROM Northwind..[Order Details])

查询执行计划表示它们都做相同的事情。如果是这样的话,推荐哪种形式?

这是基于北风的数据库。

(编辑)

刚找到这篇有用的文章: http://weblogs.sqlteam.com/mladenp/archive/2007/05/18/60210.aspx

我想我还是用“不存在”吧。


当前回答

我有一个大约有120,000条记录的表,需要只选择那些不存在的(匹配一个varchar列),在其他四个表中,行数约为1500,4000,40000,200。所有相关的表在相关的Varchar列上都有唯一的索引。

NOT IN花了大约10分钟,NOT EXISTS花了4秒。

我有一个递归查询,它可能有一些未调优的部分,这可能是10分钟的贡献,但另一个选项花了4秒解释,至少对我来说,NOT EXISTS是更好的,或者至少,IN和EXISTS并不完全相同,在继续代码之前总是值得检查。

其他回答

我在用

SELECT * from TABLE1 WHERE Col1 NOT IN (SELECT Col1 FROM TABLE2)

发现它给出了错误的结果(我说的错误是指没有结果)。因为在TABLE2.Col1中有一个NULL。

将查询更改为

SELECT * from TABLE1 T1 WHERE NOT EXISTS (SELECT Col1 FROM TABLE2 T2 WHERE T1.Col1 = T2.Col2)

给了我正确的结果。

从那时起,我开始在任何地方使用NOT EXISTS。

如果执行计划说它们是一样的,它们就是一样的。使用任何一个能让你的意图更明显的方法——在这种情况下,使用第二个。

这取决于. .

SELECT x.col
FROM big_table x
WHERE x.key IN( SELECT key FROM really_big_table );

不会相对较慢,也没有太多限制查询检查的大小,看看他们的键是否在。在这种情况下,存在是可取的。

但是,根据DBMS的优化器,这可能没有什么不同。

作为一个例子,当存在更好

SELECT x.col
FROM big_table x
WHERE EXISTS( SELECT key FROM really_big_table WHERE key = x.key);
  AND id = very_limiting_criteria

还要注意,当NOT IN为null时,NOT IN并不等同于NOT EXISTS。

这篇文章解释得很好

http://sqlinthewild.co.za/index.php/2010/02/18/not-exists-vs-not-in/

When the subquery returns even one null, NOT IN will not match any rows. The reason for this can be found by looking at the details of what the NOT IN operation actually means. Let’s say, for illustration purposes that there are 4 rows in the table called t, there’s a column called ID with values 1..4 WHERE SomeValue NOT IN (SELECT AVal FROM t) is equivalent to WHERE SomeValue != (SELECT AVal FROM t WHERE ID=1) AND SomeValue != (SELECT AVal FROM t WHERE ID=2) AND SomeValue != (SELECT AVal FROM t WHERE ID=3) AND SomeValue != (SELECT AVal FROM t WHERE ID=4) Let’s further say that AVal is NULL where ID = 4. Hence that != comparison returns UNKNOWN. The logical truth table for AND states that UNKNOWN and TRUE is UNKNOWN, UNKNOWN and FALSE is FALSE. There is no value that can be AND’d with UNKNOWN to produce the result TRUE Hence, if any row of that subquery returns NULL, the entire NOT IN operator will evaluate to either FALSE or NULL and no records will be returned

它们非常相似,但并不完全相同。

在效率方面,我发现左join is null语句更有效(当要选择大量行时)