7
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

MySQLのNOT INでNULLが含まれていると常にFALSEの結果となるらしい

Last updated at Posted at 2020-02-02

参考:https://wiki.postgresql.org/wiki/Don't_Do_This#Don.27t_use_NOT_IN
※ PostgreSQLの参考ですが、MySQLで試してみても同じだったので投稿させていただきました:bow:

-- nullが入ってない場合はtrue/false問題なし
select 
	1 in (1, 2, 3) -- true
   ,5 in (1, 2, 3) -- false
   ,1 not in (1, 2, 3) -- false
   ,5 not in (1, 2, 3); -- true

-- nullが入ってた場合は一致するのがない場合はnullになってしまう
select 
	1 in (1, 2, null) -- true
   ,5 in (1, 2, null) -- null!!!
   ,1 not in (1, 2, null) -- false
   ,5 not in (1, 2, null); -- null!!!

nullはfalseっぽい値なので、not inでnullがあるとtrueと返すのが不可能になってしまう!

select 'hoge' where 1 not in (1, null); -- 空の結果が変える
select 'hoge' where 5 not in (1, null); -- 空の結果が変える

例えばNOT INのサブクエリでnullが含まれてしまっても思った通りに動きません

create table hoge(n int);
insert into hoge
values (1),(2),(3),(4),(5),(6),(7);

create table fuga(i int);
insert into fuga
values (5),(null),(7);
-- inの場合は問題なく、fugaの5,7が一致する2レコードの結果になる
mysql> select *
    -> from hoge
    -> where n in (select * from fuga);
+------+
| n    |
+------+
|    5 |
|    7 |
+------+
2 rows in set (0.01 sec)

-- not inの場合はnullが含まれてしまうとtrueと返すことがないので、
-- 空の結果になってしまう
mysql> select *
    -> from hoge
    -> where n not in (select * from fuga);
Empty set (0.01 sec)

やり方はいろいろあると思いますが、例えば NOT EXISTSなどを使うなどすると良いと思いました

mysql> select *
    -> from hoge
    -> where not exists (select * from fuga where n = i);
+------+
| n    |
+------+
|    1 |
|    2 |
|    3 |
|    4 |
|    6 |
+------+
5 rows in set (0.00 sec)

以上です。見ていただいてありがとうございました。m(_ _)m

7
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?