MySQL“NOT IN”查询

我想运行一个简单的查询来抛出Table1所有行,其中主列值不在另一个表( Table2 )的列中。

我试过使用:

 SELECT * FROM Table1 WHERE Table1.principal NOT IN Table2.principal 

这是抛出一个语法错误。 谷歌search引导我到人们说MySQL不支持NOT IN和需要使用一些非常复杂的东西的论坛。 这是真的? 还是我犯了一个可怕的错误?

要使用IN,你必须有一个集合,用这个语法来代替:

 SELECT * FROM Table1 WHERE Table1.principal NOT IN (SELECT principal FROM table2) 

子查询选项已被回答,但请注意,在很多情况下, LEFT JOIN可以是更快的方法:

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

如果你想检查多个表,以确保它不存在于任何表(如SRKR的评论),你可以使用这个:

 SELECT table1.* FROM table1 LEFT JOIN table2 ON table2.name=table1.name LEFT JOIN table3 ON table3.name=table1.name WHERE table2.name IS NULL AND table3.name IS NULL 

不在与不存在与左join/在MySQL中为NULL

除了SQL Server之外,MySQL以及其他所有系统都能够优化LEFT JOIN / IS NULL ,只要find匹配值就返回FALSE ,并且它是关心logging此行为的唯一系统。 […]由于MySQL不能使用HASHMERGE连接algorithm,唯一的ANTI JOIN能够使用NESTED LOOPS ANTI JOIN

[…]

实质上, [ NOT IN ]LEFT JOIN / IS NULL使用的计划完全相同,尽pipe这些计划是由不同的代码分支执行的,并且在EXPLAIN结果中看起来不同。 事实上这些algorithm实际上是相同的,查询在同一时间完成。

[…]

使用NOT EXISTS性能下降的确切原因很难确定,因为这个下降是线性的,只要这两个字段都被索引,似乎并不取决于数据分布,两个表中的值的数量等。 由于MySQL中有三个代码需要做一项工作,因此负责EXISTS的代码可能会进行某种额外的检查,这会花费额外的时间。

[…]

MySQL可以优化所有三种方法来做一个NESTED LOOPS ANTI JOIN 。 然而,这三种方法产生了三种不同的计划,由三个不同的代码执行。 执行EXISTS谓词的代码的效率降低了大约30%

这就是为什么在MySQL中search缺失值最好方法是使用LEFT JOIN / IS NULLNOT IN而不是NOT EXISTS

(强调增加)

不幸的是,这似乎是MySql使用“NOT IN”子句的问题,下面的屏幕截图显示了子查询选项返回错误的结果:

 mysql> show variables like '%version%'; +-------------------------+------------------------------+ | Variable_name | Value | +-------------------------+------------------------------+ | innodb_version | 1.1.8 | | protocol_version | 10 | | slave_type_conversions | | | version | 5.5.21 | | version_comment | MySQL Community Server (GPL) | | version_compile_machine | x86_64 | | version_compile_os | Linux | +-------------------------+------------------------------+ 7 rows in set (0.07 sec) mysql> select count(*) from TABLE_A where TABLE_A.Pkey not in (select distinct TABLE_B.Fkey from TABLE_B ); +----------+ | count(*) | +----------+ | 0 | +----------+ 1 row in set (0.07 sec) mysql> select count(*) from TABLE_A left join TABLE_B on TABLE_A.Pkey = TABLE_B.Fkey where TABLE_B.Pkey is null; +----------+ | count(*) | +----------+ | 139 | +----------+ 1 row in set (0.06 sec) mysql> select count(*) from TABLE_A where NOT EXISTS (select * FROM TABLE_B WHERE TABLE_B.Fkey = TABLE_A.Pkey ); +----------+ | count(*) | +----------+ | 139 | +----------+ 1 row in set (0.06 sec) mysql> 

小心NOT IN不是<> ANY的别名,而是<> ALL

http://dev.mysql.com/doc/refman/5.0/en/any-in-some-subqueries.html

 SELECT c FROM t1 LEFT JOIN t2 USING (c) WHERE t2.c IS NULL 

不能'被replace

 SELECT c FROM t1 WHERE c NOT IN (SELECT c FROM t2) 

你必须使用

 SELECT c FROM t1 WHERE c <> ANY (SELECT c FROM t2)