在对SQL语句进行性能优化时,经常用到一个技巧是将IN改写成EXISTS,这是等价改写,并没有什么问题。问题在于,将NOT IN改写成NOT EXISTS时,结果未必一样。
执行环境:MySQL
一、举例验证
例如,有如下一张表 rr 。要求:选择4月2号的数据,并且其type1是4月1号没有的(从表看,就是4月2号C的那条)。
- 使用NOT IN ,单纯按照这个条件去实现
select * from rr
where create_date='2024-04-02'
and type1 not in (
select type1 from rr
where create_date='2024-04-01'
)
;
- 使用NOT EXISTS
select r1.* from rr as r1
where r1.create_date='2024-04-02'
and not exists (
select r2.type1 from rr as r2
where r2.create_date='2024-04-01' and r1.type1=r2.type1
)
;
主要原因是4月1号的数据中,存在type1为NULL的。如果该type1不是NULL,使用NOT IN就可以正确找出来结果了。
其中的原理涉及三值逻辑。