参考文章里作者是这样写的:

a 左连接 b,查询 a 中没有的 b 记录

select id,`name` FROM a LEFT JOIN
(select id as i FROM b) as c
ON a.id=c.i where c.i IS NULL;

b 左连接 a,查询 b 中没有的 a 记录

select id,`name` FROM b LEFT JOIN
(select id as i FROM a) as c
ON b.id=c.i where c.i IS NULL;

为什么不直接用左连接查询呢?一开始我以为是判断字段为空的条件限制,后来直接去掉子查询发现查询结果集一致,速度反而快了 N 多倍。

测试过程如下:

测试工具:Navicat

数据库存在这样两个表 member 和 company,分别存储会员账号信息和会员公司信息,数据记录都在 4 万 - 5 万的样子。

发现存在 uid 记录不完整的情况,即 member 表存在记录,但 company 表不存在;相反的情况也是。

先是用参考文档里的模式,复刻了一版查询 sql:

select uid FROM member LEFT JOIN
(select uid as i FROM company) as t1
ON member.uid=t1.i where t1.i IS NULL;

查询时间为 48 秒左右。

然后去掉里面的子查询

select member.uid FROM member LEFT JOIN
company as t1
ON member.uid=t1.uid where t1.uid IS NULL;

查询时间为 0.001 秒,内容与添加了子查询的结果一致。

再尝试被原作者摒弃的效率很低的 where not in 模式:

select member.uid FROM member NOT IN 
(select uid as i FROM company) ;

查询时间为 0.052 秒,内容与添加了子查询的结果一致。

从结果去分析,查询效率对比,直接左连接 > where not in > 左连接子查询。

从结果推测,原作者要么是因为当时 MySQL 版本不支持直接左连接(应该不会吧!),要么就是误用了子查询。

参考文章:Mysql 求两个表(查询结果)的差集