NOT EXISTS与NOT IN和LEFT JOIN之间的区别是什么?

时间:2010-02-11 18:39:37

标签: sql

在我看来,你可以在SQL查询中使用NOT EXISTS,NOT IN或LEFT JOIN WHERE为NULL来做同样的事情。例如:

SELECT a FROM table1 WHERE a NOT IN (SELECT a FROM table2)

SELECT a FROM table1 WHERE NOT EXISTS (SELECT * FROM table2 WHERE table1.a = table2.a)

SELECT a FROM table1 LEFT JOIN table2 ON table1.a = table2.a WHERE table1.a IS NULL

我不确定我的语法是否正确,但这些是我见过的一般技巧。为什么我会选择使用一个而不是另一个?性能有所不同......?哪一个是最快/最有效的? (如果它取决于实施,我何时会使用每一个?)

5 个答案:

答案 0 :(得分:126)

简而言之:

NOT IN有点不同:如果列表中只有一个NULL,它就不会匹配。

  • MySQL中,NOT EXISTS效率稍低

  • SQL Server中,LEFT JOIN / IS NULL效率较低

  • PostgreSQL中,NOT IN效率较低

  • Oracle中,所有三种方法都相同。

答案 1 :(得分:5)

如果数据库擅长优化查询,那么第一个数据库将转换为接近第三个数据库。

对于像你一样的简单情况,应该有很少或没有区别,因为它们都将作为连接执行。在更复杂的查询中,数据库可能无法从not innot exists查询中进行联接。在这种情况下,查询会慢得多。另一方面,如果没有可以使用的索引,连接也可能表现不佳,因此仅仅因为您使用连接并不意味着您是安全的。您必须检查查询的执行计划,以判断是否存在任何性能问题。

答案 2 :(得分:2)

假设您避免使用空值,它们都是使用标准SQL编写anti-join的方法。

明显的遗漏是使用EXCEPT

的等价物
SELECT a FROM table1
EXCEPT
SELECT a FROM table2

请注意,在Oracle中,您需要使用MINUS运算符(可以说是一个更好的名称):

SELECT a FROM table1
MINUS
SELECT a FROM table2

说到专有语法,根据您使用的产品,可能还有非标准的等价物值得研究,例如: SQL Server中的OUTER APPLY(类似):

SELECT t1.a
  FROM table1 t1
       OUTER APPLY 
       (
        SELECT t2.a
          FROM table2 t2
         WHERE t2.a = t1.a
       ) AS dt1
 WHERE dt1.a IS NULL;

答案 3 :(得分:0)

当需要在具有多字段主键的表中插入数据时,请考虑它会更快(我在Access中尝试但我认为在任何数据库中)不检查“不存在具有'此类'值的记录表“, - 而只是插入表中,多余的记录(通过键)将不会被插入两次。

答案 4 :(得分:0)

性能视角始终避免使用NOT IN,NOT EXISTS等反向关键字...... 因为要检查DBMS需要运行所有可用的逆项,并删除反向选择。