MySQL“不在”查询

o75abkj4  于 2023-03-17  发布在  Mysql
关注(0)|答案(6)|浏览(145)

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

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

相反,这是一个语法错误。谷歌搜索把我带到了一些论坛,人们说MySQL不支持NOT IN,需要使用一些非常复杂的东西。这是真的吗?还是我犯了一个可怕的错误?

unguejic

unguejic1#

要使用IN,必须有一个集合,请改用以下语法:

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

uurv41yg2#

子查询选项已经回答过了,但请注意,在许多情况下,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
dvtswwa3

dvtswwa33#

MySQL以及除SQL Server之外的所有其他系统都能够优化**LEFT JOIN/IS NULL,以便在找到匹配值时立即返回FALSE,并且它是唯一关心记录此行为的系统。[...]由于MySQL无法使用HASHMERGE连接算法,ANTI JOIN的唯一功能是NESTED LOOPS ANTI JOIN
[...]
从本质上讲,[NOT IN]LEFT JOIN/IS NULL使用的计划完全相同,尽管这些计划由不同的代码分支执行,并且在EXPLAIN的结果中看起来不同。实际上,算法是相同的,查询在同一时间完成。
[...]
很难说 [使用**NOT EXISTS**时性能下降] 的确切原因,因为这种下降是线性的,似乎不依赖于数据分布、两个表中的值的数量等,只要两个字段都被索引。由于MySQL中有三段代码基本上完成一项工作,负责X1 M12 N1 X的代码可能进行某种额外的检查,这会花费额外的时间。
[...]
MySQL可以优化所有三个方法来做一种NESTED LOOPS ANTI JOIN。[...]然而,这三个方法生成三个不同的计划,由三段不同的代码执行。执行EXISTS predicate 的代码效率要低大约30% [...]
这就是为什么
在MySQL中搜索缺失值的最佳方法是使用LEFT JOIN/IS NULLNOT IN,而不是NOT EXISTS。**
(着重号后加)

pexxcrt2

pexxcrt24#

小心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)
vh0rcniy

vh0rcniy5#

不幸的是,这似乎是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>
30byixjq

30byixjq6#

以上答案都是正确的,但是很难理解,为了更清楚,我举个例子来回答,假设你要选择所有不在优秀表中的人:
备选案文1:

select *
 from persons p
 where not exists(select * 
                 from outstandings o
                 where p.id = o.id)

备选案文2:

select *
    from persons p
    where p.id not in( select m.id
                      from outstandings o
                      where m.id = o.id)

备选案文3:

select *
    from persons p
    left join utstandings o on o.id=p.id
    where o.id in null

相关问题