目录
案例2:当主表中有null,采用not in且not in后面不为子查询的时候会忽略NULL,匹配不到NULL,即查询不到任何NULL的记录
案例4:如果not in后面跟子查询时,所选的字段包含NULL值要特别注意
- create table t as
- select '张三' as name,1 as class
- union all
- select '李四' as name,1 as class
- union all
- select '王五' as name,2 as class
- union all
- select '老六' as name,null as class
- union all
- select '陈七' as name, 4 as class
- union all
- select '赵八' as name, 5 as class
- union all
- select '孙九' as name, 5 as class
原表数据如下:

select * from t where class in (null,'1')
in相当于or,对于null值得判断不是is null而是等于,因而对于NULL值得判断永远都是false
select * from t where class ='1' or class =null

如果想得到NULL的结果,一定要对NULL的值做转换,可以采用如下SQL
select * from t where coalesce(class,'null') in ('null','1')

结论:当in中包含 null,不会获取NULL的结果
select * from t where class not in ('1','2')

select * from t where class not in ('1','2',null)
not in 相当于and条件,只要有一个false,那么所有的都为false我们知道in not in都是用等号(=)来判断的,对于null不会使用is not null那么上面改写为:
select * from t where class !='1'and !='2'and !=null
结果如下:

由于判读不等于NULL永远为false,所有整个条件判断都为false,where中为flase
那么结果将什么也不会返回对于 要过滤null的情况,可以这样改写,将null转换为字符串'null',SQL如下:
select * from t where coalesce(class,'null') not in ('1','2','null')

如下SQL:
- select *
- from t
- where class not in (
- select class
- from t t1
- where coalesce(t1.class, 'null') in (1, 2, 'null'))

最终返回结果为空,原因是子查询中包含了NULL值,对于这种情况一定要特别注意,当not in中包含子查询时,如果结果中包含NULL值,将查不到任何结果,此时应该需要主动在子查询中将NULL值过滤掉。
- create table t1 as
- select 1 as class
- union all
- select 2 as class
- union all
- select 3 as class
- union all
- select 4 as class
- union all
- select null as class
- union all
- select null as class
-
- select *
- from t
- where class not in (
- select class
- from t1
- )
最终结果为空

正确的写法如下:
- select *
- from t
- where class not in (
- select class
- from t1
- where class is not null
- )

此处有个问题,我们子查询中的接入如下:
- select class
- from t1
- where class is not null

那么上述的结果与如下SQL等价吗?
select * from t where class not in (1,2,3,4)
执行上述SQL:我们得到的结果如下

显然两个SQL不等价,也就是说当not in 中有子查询的时候,主表中的NULL不会忽略,可以得到主表NULL的结果,当not in中是常量值得时候,主表中的NULL被忽略,这个略有点坑。
如果非要过滤掉NULL值,可以按如下写法
- select *
- from t
- where coalesce(class,'null') not in (
- select coalesce(class,'null')
- from t1
- )

总之用in的时候一般问题不大,使用not in的时候需要特别主要,结合本文恰当使用,之所以
造成如此大的差异原因是对NULL的判断上,NULL的判断本质上is null或is not null,in或
not in的判断是等于(=),所以对NULL判断是无效的,需要谨记。