用于查找一个表中但不在另一个表中的行的 MySQL 查询

Posted

技术标签:

【中文标题】用于查找一个表中但不在另一个表中的行的 MySQL 查询【英文标题】:MySQL query for finding rows that are in one table but not another 【发布时间】:2013-08-01 17:20:27 【问题描述】:

假设我在两个表中有大约 25,000 条记录,并且每个表中的数据应该相同。如果我需要查找表 A 中但不在表 B 中的任何行,那么最有效的方法是什么。

我们已经将它作为一个表的子查询和NOT IN 的结果进行了尝试,但这运行了 10 多分钟,几乎使我们的网站崩溃。

一定有更好的方法。也许是JOIN

【问题讨论】:

【参考方案1】:

希望LEFT OUTER JOIN 能完成这项工作

select t1.similar_ID 
    , case when t2.similar_ID is not null then 1 else 0 end as row_exists
from table1 t1
left outer join (select distinct similar_ID from table2) t2
   on t1.similar_ID  = t2.similar_ID // your WHERE goes here

【讨论】:

【参考方案2】:

I would suggest you read the following blog post, which goes into great detail on this question:

哪种方法最好选择一个表中存在但缺失的值 在另一个?

经过深入分析,得出以下结论:

但是,这三种方法[NOT INNOT EXISTSLEFT JOIN] 生成三个不同的计划,由三个不同的执行 段代码。执行EXISTS谓词的代码大约是30% 比执行index_subqueryLEFT JOIN 的效率低 优化为使用Not exists 方法。

这就是为什么在 mysql 中搜索缺失值的最佳方法是使用 LEFT JOIN / IS NULLNOT IN 而不是 NOT EXISTS

如果您使用NOT IN 看到的性能不令人满意,您将无法通过切换到LEFT JOIN / IS NULLNOT EXISTS 来提高此性能,而是需要采取优化此查询的不同途径,例如添加索引

【讨论】:

我喜欢 Quassnoi 的帖子——我只是希望他们能更频繁一些。也就是说,我认为最新版本的 MySQL 一定以某种方式改进了 IN 和 EXISTS 的优化,因为在我的系统上测试相同的 DDL 和 DML 返回几乎完全相反的性能统计数据: LEFT JOIN: 12.43;不在 6.04 中;不存在:5.93。顺便说一句,一个 JOIN(0 个结果)在 0 秒内执行。 @Strawberry 好点...该分析是在大约 4 年前完成的。我很惊讶LEFT JOIN 花费的时间是其他方法的两倍......但是NOT INNOT EXISTS 彼此相差 2%,我仍然建议 OP 考虑索引这些表,因为两个 25k 行的表之间的反连接应该需要几毫秒,而不是几分钟。 这家伙知道他在说什么。索引就是答案。【参考方案3】:

改用exixts and not exists 函数

Select * from A where not exists(select * from B);

【讨论】:

OP 要求加入,因为子查询需要很多时间 他用的是not in. Not exists要快很多 引擎如何解析not exists,使其更快。我不是在问你,我只是想知道。【参考方案4】:

左连接。来自the mysql documentation

如果ON或USING中右表没有匹配行 在 LEFT JOIN 中,所有列都设置为 NULL 的行用于 正确的表。您可以使用这个事实来查找表中的行 在另一个表中没有对应项:

SELECT left_tbl.* FROM left_tbl LE​​FT JOIN right_tbl ON left_tbl.id = right_tbl.id WHERE right_tbl.id 为空;

此示例查找 left_tbl 中 id 值不是 存在于 right_tbl 中(即,left_tbl 中的所有行没有 right_tbl 中的对应行)。

【讨论】:

以上是关于用于查找一个表中但不在另一个表中的行的 MySQL 查询的主要内容,如果未能解决你的问题,请参考以下文章

SQL删除不在另一个表中的行

如何索引不在另一个表中的值

mysql更新一个表不在另一个表中的数据

在一个文件中查找不在另一个文件中的行的快速方法?

如何获取一个MySql表中存在的记录而不是另一个[重复]

sql server 2000返回在第一个表中但不在第二个表中的数据