共计 1568 个字符,预计需要花费 4 分钟才能阅读完成。
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 t1
where 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 test1
where id1 in (select id2 from test2)
后果是:
OK 木有问题!
然而如果我一时手滑,写成了:
select id1 from test1
where 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 test1
where 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 开发手册(嵩山版)》最新公布,速速下载!
感觉不错,别忘了顺手点赞 + 转发哦!