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不能使用HASH
和MERGE
连接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 NULL
或NOT 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)