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开发手册(嵩山版)》最新公布,速速下载!

感觉不错,别忘了顺手点赞+转发哦!