我想运行一个简单的查询,以抛出所有Table1
其他表(Table2
)的列中不存在主体列值的行。
我尝试使用:
SELECT * FROM Table1 WHERE Table1.principal NOT IN Table2.principal
而是抛出语法错误。Google搜索使我进入了一个论坛,那里的人们说MySQL不支持NOT IN
,因此需要使用极其复杂的东西。这是真的?还是我犯了一个可怕的错误?
我想运行一个简单的查询,以抛出所有Table1
其他表(Table2
)的列中不存在主体列值的行。
我尝试使用:
SELECT * FROM Table1 WHERE Table1.principal NOT IN Table2.principal
而是抛出语法错误。Google搜索使我进入了一个论坛,那里的人们说MySQL不支持NOT IN
,因此需要使用极其复杂的东西。这是真的?还是我犯了一个可怕的错误?
Answers:
要使用IN,您必须有一个set,请改用以下语法:
SELECT * FROM Table1 WHERE Table1.principal NOT IN (SELECT principal FROM table2)
table2.principal
可以NULL
。在这种情况下,NOT IN
将始终返回,FALSE
因为NOT IN
将其视为<> ALL
,它将像这样比较子查询中的所有行,与进行比较Table1.principal <> table2.principal
时失败NULL
:Table1.principal <> NULL
将不会导致TRUE
。解决方法:NOT IN (SELECT principal FROM table2 WHERE principal IS NOT NULL)
。
subquery选项已经被回答,但是请注意,在许多情况下,a 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
NOT IN
&具有相同的性能LEFT JOIN
。两者都+1
MySQL,以及除SQL Server之外的所有其他系统,都能够优化
LEFT JOIN
/IS NULL
在FALSE
找到匹配值后立即返回,这是唯一记录此行为的系统。[…]由于MySQL无法使用HASH
和MERGE
加入算法,因此ANTI JOIN
它唯一能够使用的是NESTED LOOPS ANTI JOIN
[…]
本质上,[
NOT IN
]与LEFT JOIN
/IS NULL
使用的计划完全相同,尽管这些计划是由不同的代码分支执行的,并且它们在结果中看起来也有所不同EXPLAIN
。这些算法实际上是相同的,并且查询是同时完成的。
[…]
很难说出[使用
NOT EXISTS
] 时性能下降的确切原因,因为这种下降是线性的,并且似乎不依赖于数据分布,两个表中值的数量等,只要对两个字段都进行了索引。由于MySQL中有三段代码本质上只能完成一项工作,因此负责该代码的代码有可能EXISTS
进行某种额外的检查,而这需要花费额外的时间。
[…]
MySQL可以优化所有三种方法来执行某种操作
NESTED LOOPS ANTI JOIN
。[…]但是,这三种方法生成三种不同的计划,这些计划由三种不同的代码执行。执行EXISTS
谓词的代码的效率大约降低30%[…]这就是为什么在MySQL中搜索缺失值的最佳方法是使用
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
不能被替换
SELECT c FROM t1 WHERE c NOT IN (SELECT c FROM t2)
您必须使用
SELECT c FROM t1 WHERE c <> ANY (SELECT c FROM t2)