在我看来,你可以在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
我不确定我的语法是否正确,但这些是我见过的一般技巧。为什么我会选择使用一个而不是另一个?性能有所不同......?哪一个是最快/最有效的? (如果它取决于实施,我何时会使用每一个?)
答案 0 :(得分:126)
简而言之:
NOT IN
有点不同:如果列表中只有一个NULL
,它就不会匹配。
在MySQL
中,NOT EXISTS
效率稍低
在SQL Server
中,LEFT JOIN / IS NULL
效率较低
在PostgreSQL
中,NOT IN
效率较低
在Oracle
中,所有三种方法都相同。
答案 1 :(得分:5)
如果数据库擅长优化查询,那么第一个数据库将转换为接近第三个数据库。
对于像你一样的简单情况,应该有很少或没有区别,因为它们都将作为连接执行。在更复杂的查询中,数据库可能无法从not in
和not 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需要运行所有可用的逆项,并删除反向选择。