0
1

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.

NULLが絡むIN/NOT IN の挙動 (MySQL)

Posted at

MysqlのNOT IN句はNULLが絡むと初見ではちょっと気付けない挙動をします。MySQL以外でどうなのかは知りませんが。

以下のような見やすいテーブルの話をします。

id num name
1 1 hello
2 2 world
3 NULL !

まずは以下のクエリと実行結果を御覧ください。

SELECT * FROM `mytable` WHERE `num` IN (1, 3);

id, num, name
1, 1, hello

はい、特に不審な点はありませんね。
では次。

NULLの霊圧が…消えた…?

SELECT * FROM `mytable` WHERE `num` NOT IN (1, 3);

id, num, name
2, 2, world
SELECT * FROM `mytable` WHERE `num` IN (1, 3, NULL);

id, num, name
1, 1, hello

どうやら値がNULLだとINにもNOT INにも引っかからなくなるようです。:thinking:
ちなみに IN ('')NOT IN ('')でもNULLは引っかからない。

そして誰もいなくなった

SELECT * FROM `mytable` WHERE `num` NOT IN (1, 3, NULL);

id, num, name

0件。

分かった、条件にNULLを含めなければ良いんだな

…と思うじゃん?
油断すると簡単に以下のようなクエリになったりします。

SELECT * FROM `another_table` WHERE `another_table`.`id` NOT IN( 
    SELECT `num` FROM `mytable` 
);

この場合サブクエリ部分が(1, 2, NULL) となって1行も返ってこない悲しい結果になります。

回避方法

サブクエリ内でWHERE に IS NOT NULL を追加するなどしましょう。

SELECT * FROM `another_table` WHERE `another_table`.`id` NOT IN(
    SELECT num FROM `mytable` WHERE `num` IS NOT NULL
);
0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?