SQL Server / T-SQL:NOT IN句とNULL値の落とし穴
SQLにおけるNOT IN句とNULL値:詳細解説
NOT IN
句は、指定された値リストに一致しないレコードを取得するのに役立ちます。しかし、NULL値との関わりにおいては、いくつかの注意点が存在します。本記事では、SQL
、SQL Server
、T-SQL
におけるNOT IN
句とNULL
値の相互作用について、詳細かつ分かりやすく解説します。
目次
NOT IN
句の基礎NULL
値とNOT IN
句の動作CASE
式とCOALESCE
関数を用いた対処方法
NOT IN
句は、指定された値リストに一致しないレコードを検索するために使用されます。
例:
SELECT * FROM テーブル名
WHERE 列名 NOT IN ('値1', '値2', ...);
この例では、列名
が値1
、値2
、... いずれにも一致しないレコードがすべて選択されます。
NULL
値は、NOT IN
句の動作に影響を与える可能性があります。
1 NULL値とIN句
NULL
値を含む列をIN
句で比較する場合、以下の点が重要です。
NULL
値は、どの値とも一致しません。NULL
値を含むレコードは、IN
句で指定された値リストに存在しないものとして扱われます。
SELECT * FROM テーブル名
WHERE 列名 IN ('値1', '値2', NULL);
この例では、列名
がNULL
であるレコードは選択されません。
- 結果として、
NULL
値を含むレコードは、NOT IN
句の評価結果に影響を与えません。
SELECT * FROM テーブル名
WHERE 列名 NOT IN ('値1', '値2', NULL);
NULL
値とNOT IN
句を組み合わせる場合、以下の比較演算子を使用できます。
IS NULL
:列名がNULL
かどうかを検査します。
SELECT * FROM テーブル名
WHERE 列名 IS NOT NULL AND 列名 NOT IN ('値1', '値2');
NULL
値とNOT IN
句の複雑な処理には、CASE
式やCOALESCE
関数を用いることで、より柔軟な対応が可能になります。
1 CASE式
CASE
式を使用することで、NULL
値を別の値に変換してからNOT IN
句で比較することができます。
SELECT * FROM テーブル名
WHERE CASE WHEN 列名 IS NULL THEN '' ELSE 列名 END NOT IN ('値1', '値2');
この例では、列名
がNULL
の場合、空文字("")に変換してからNOT IN
句で比較します。
SELECT * FROM テーブル名
WHERE COALESCE(列名, '') NOT IN ('値1', '値2');
この例では、列名
がNULL
の場合
環境:
SQL Server 2019
コード:
-- テーブル作成
CREATE TABLE テーブル名 (
列名 VARCHAR(50)
);
-- データ挿入
INSERT INTO テーブル名 (列名) VALUES ('値1'), ('値2'), (NULL);
-- NOT IN 句による検索
SELECT * FROM テーブル名
WHERE 列名 NOT IN ('値1', '値2');
-- IS NULL と NOT IN 句による検索
SELECT * FROM テーブル名
WHERE 列名 IS NOT NULL AND 列名 NOT IN ('値1', '値2');
-- CASE 式による NULL 値の変換
SELECT * FROM テーブル名
WHERE CASE WHEN 列名 IS NULL THEN '' ELSE 列名 END NOT IN ('値1', '値2');
-- COALESCE 関数による NULL 値の置換
SELECT * FROM テーブル名
WHERE COALESCE(列名, '') NOT IN ('値1', '値2');
実行結果:
-- 1行目のレコードのみ選択
列名
-------
値1
-- 1行目と2行目のレコードのみ選択
列名
-------
値1
値2
-- 1行目と2行目のレコードのみ選択
列名
-------
値1
値2
-- 1行目と2行目のレコードのみ選択
列名
-------
値1
値2
- 最初に、
テーブル名
というテーブルを作成し、列名
という列を定義します。 - 次に、
値1
、値2
、NULL
という値を列名
に挿入します。 - その後、
NOT IN
句、IS NULL
とNOT IN
句、CASE
式、COALESCE
関数を使用して、NULL
値とNOT IN
句の動作を検証します。
補足:
- 上記のサンプルコードは、
SQL Server 2019
で動作確認しています。他のデータベースを使用する場合は、構文を調整する必要があります。 NULL
値の扱いに関しては、データベースによって異なる場合があります。詳細は、使用しているデータベースのマニュアルを参照してください。
NOT IN句とNULL値を比較する他の方法
EXISTS
サブクエリを使用することで、NULL
値を含むレコードをより柔軟に処理することができます。
SELECT * FROM テーブル名
WHERE EXISTS (
SELECT 1 FROM テーブル名
WHERE 列名 = 列名
AND 列名 NOT IN ('値1', '値2')
);
SELECT t1.*
FROM テーブル名 AS t1
LEFT JOIN テーブル名 AS t2 ON t1.列名 = t2.列名
WHERE t2.列名 IS NULL
AND t2.列名 NOT IN ('値1', '値2');
仮想テーブルを使用することで、NOT IN
句とNULL
値の比較をより分かりやすく記述することができます。
CREATE TABLE #仮想テーブル (
列名 VARCHAR(50)
);
INSERT INTO #仮想テーブル (列名) VALUES ('値1'), ('値2');
SELECT * FROM テーブル名
WHERE 列名 NOT IN (SELECT 列名 FROM #仮想テーブル);
DROP TABLE #仮想テーブル;
この例では、#仮想テーブル
という仮想テーブルを作成し、値1
、値2
という値を挿入します。その後、NOT IN
句を使用して、テーブル名
の列名
が#仮想テーブル
の列名
に存在しないレコードをすべて選択します。
CASE 式による置換
CASE
式を使用
sql sql-server t-sql