WHY?
IN 和 NOT IN 是比拟罕用的关键字,为什么要尽量避免呢?
1、效率低
我的项目中遇到这么个状况:
t1表 和 t2表 都是150w条数据,600M的样子,都不算大。
然而这样一句查问 ↓
select * from t1 where phone not in (select phone from t2)
间接就把我跑傻了。。。
十几分钟,查看了一下 phone在两个表都建了索引,字段类型也是一样的。原来 not in 是不能命中索引的。。。。
改成 NOT EXISTS 之后查问 20s ,效率真的差好多。
select * from t1where not EXISTS (select phone from t2 where t1.phone =t2.phone)
2、容易呈现问题,或查问后果有误 (不能更重大的毛病)
以 IN 为例。
建两个表:test1 和 test2
create table test1 (id1 int)create table test2 (id2 int)insert into test1 (id1) values (1),(2),(3)insert into test2 (id2) values (1),(2)
我想要查问,在test2中存在的 test1中的id 。
应用 IN 的个别写法是:
select id1 from test1where id1 in (select id2 from test2)
后果是:
OK 木有问题!
然而如果我一时手滑,写成了:
select id1 from test1where id1 in (select id1 from test2)
不小心把id2写成id1了 ,会怎么样呢?
后果是:
EXCUSE ME!为什么不报错?
独自查问 select id1 from test2
是肯定会报错: 音讯 207,级别 16,状态 1,第 11 行 列名 'id1' 有效。
然而应用了IN的子查问就是这么搪塞,间接查出 1 2 3
这仅仅是容易出错的状况,本人不写错还没啥事儿,上面来看一下 NOT IN 间接查出谬误后果的状况:
给test2插入一个空值:
insert into test2 (id2) values (NULL)
我想要查问,在test2中不存在的 test1中的 id 。
select id1 from test1where id1 not in (select id2 from test2)
后果是:
空白!显然这个后果不是咱们想要的。咱们想要3。为什么会这样呢?
起因是:NULL不等于任何非空的值啊!如果id2只有1和2, 那么3<>1 且 3<>2 所以3输入了,然而 id2蕴含空值,那么 3也不等于NULL 所以它不会输入。
跑题一句:建表的时候最好不要容许含空值,否则问题多多。
HOW?
1、用 EXISTS 或 NOT EXISTS 代替
select * from test1 where EXISTS (select * from test2 where id2 = id1 )select * FROM test1 where NOT EXISTS (select * from test2 where id2 = id1 )
2、用JOIN 代替
select id1 from test1 INNER JOIN test2 ON id2 = id1 select id1 from test1 LEFT JOIN test2 ON id2 = id1 where id2 IS NULL
妥妥的没有问题了!
PS:那咱们死活都不能用 IN 和 NOT IN 了么?并没有,一位大神已经说过,如果是确定且无限的汇合时,能够应用。如 IN (0,1,2)。
作者:Hydor\
起源:https://www.cnblogs.com/hydor...
近期热文举荐:
1.1,000+ 道 Java面试题及答案整顿(2022最新版)
2.劲爆!Java 协程要来了。。。
3.Spring Boot 2.x 教程,太全了!
4.别再写满屏的爆爆爆炸类了,试试装璜器模式,这才是优雅的形式!!
5.《Java开发手册(嵩山版)》最新公布,速速下载!
感觉不错,别忘了顺手点赞+转发哦!