NOT IN を使う時は NULL に特に注意!

NOT IN を使う時は NULL に特に注意!

以前、「NULL の取り扱い方 」 で、カラムの値が NULL の時の取り扱いの注意点について書きました。

今回は NOT IN で条件を指定する際には、特に NULL には注意が必要です、というお話です。

ANSI_NULLS は ON の前提です。 ANSI_NULLS オプションについては、「NULL の取り扱い方 」 をご覧ください。


NOT IN で指定したサブクエリーに NULL が存在すると。。。

NOT IN で指定したリストやサブクエリーの値に NULL が存在すると、常に空の結果セットが返ってきてしまいます。


実際に例を見てみましょう。

次のような Student テーブルと TestResult テーブルがあります。

NOT IN を使う時は NULL に特に注意 1


TestResult テーブルに存在していない Student のレコードを取得したいとします。

その時に次のようにクエリーを書いてしまうと、空の結果セットが返ってきて期待通りの結果にはなりません。

SELECT	*
FROM	Student
WHERE	StudentID NOT IN 
		(SELECT StudentID 
		 FROM	TestResult);

[実行結果]
NOT IN を使う時は NULL に特に注意 2

理由は NOT IN は、リストやサブクエリーで指定した全ての値との StudentID <> [値] が TRUE となるレコードのみを返すのですが、StudentID <> NULL は常に FALSE になるからです。


ですので、NOT IN で指定するカラムに NULL が入る可能性がある時は、次のように WHERE 句で IS NOT NULL を指定する必要があります。

SELECT	*
FROM	Student
WHERE	StudentID NOT IN 
		(SELECT StudentID 
		 FROM	TestResult
		 WHERE	StudentID IS NOT NULL);

[実行結果]
NOT IN を使う時は NULL に特に注意 3


私は、NOT IN も使いますが、NULL を気にしなくて良い、必要であれば複数のカラムで条件を指定することができる、パフォーマンスが NOT IN と同じか良くなることが多い、などの理由で NOT IN の代わりに NOT EXISTS を使うことのほうが多いです。

SELECT	*
FROM	Student AS S
WHERE	NOT EXISTS
		(SELECT * 
		 FROM	TestResult AS TR
		 WHERE	TR.StudentID = S.StudentID);

[実行結果]
NOT IN を使う時は NULL に特に注意 4

© 2010-2024 SQL Server 入門