6.

SQL CASE文 で NULL を判定する方法(IS NULL / COALESCE / NVL / NULLIF / 互換性ガイド)

編集
この記事の要点
  • SQL の CASE 式で NULL を判定する場合、WHEN col IS NULL を使う — WHEN col = NULL常に NULLを返すため誤り
  • NULL = NULLtrue ではなく NULL(三値論理:true / false / NULL)
  • 同等の処理は COALESCE(col1, col2)(NULL なら次の引数)で書ける — ANSI SQL 標準
  • Oracle なら NVL(col1, col2)、SQL Server なら ISNULL(col1, col2)
  • CASE 式は SELECT / WHERE / ORDER BY / UPDATE のあらゆる箇所で使える便利な条件分岐

CASE 式と NULL 判定

SQL の CASE 式で「NULL なら別の値、そうでなければそのまま」のような条件分岐を書く場面はよくあります。ところが NULL の判定には独特のルールがあり、= で書くと意図通りに動きません。

NG 例 — = NULL は機能しない

-- これは意図通りに動かない!
SELECT
    CASE WHEN col1 = NULL THEN col2 ELSE col1 END
FROM test_table;

SQL の三値論理(true / false / NULL)では、NULL = NULLtrue ではなく NULL を返します。WHEN は true のときだけ THEN 側を返すため、結局すべての行で ELSE col1 が選ばれてしまいます。

正しい書き方 — IS NULL

SELECT
    CASE WHEN col1 IS NULL THEN col2 ELSE col1 END
FROM test_table;

NULL の判定には専用の演算子 IS NULL / IS NOT NULL を使います。これは = と違って必ず true / false を返す点が重要です。

具体例

テーブル

idcol1col2
1AX
2NULLY
3CZ

クエリ

SELECT
    id,
    CASE WHEN col1 IS NULL THEN col2 ELSE col1 END AS result
FROM test_table;

結果

idresult
1A
2Y
3C

もっと簡潔に — COALESCE

COALESCE引数を左から順に評価し、最初に NULL でない値を返す関数。ANSI SQL 標準で、ほぼ全ての RDBMS で使えます。

-- CASE 式と同じ結果
SELECT COALESCE(col1, col2) FROM test_table;

-- 3 つ以上もOK
SELECT COALESCE(col1, col2, col3, 'デフォルト') FROM test_table;

RDBMS 別の関数比較

RDBMS関数
標準 SQL / 全DBCOALESCECOALESCE(col1, col2)
OracleNVLNVL(col1, col2)
OracleNVL2NVL2(col1, 値1, 値2)
SQL ServerISNULLISNULL(col1, col2)
MySQLIFNULLIFNULL(col1, col2)
MySQLIFIF(col1 IS NULL, col2, col1)

逆パターン — IS NOT NULL

NULL じゃないなら〜」を判定したい場合は IS NOT NULL

SELECT
    CASE WHEN email IS NOT NULL THEN '連絡可' ELSE '連絡不可' END AS status
FROM users;

NULLIF — 値を NULL に変換

逆に「ある値を NULL として扱いたい」場面では NULLIF が便利。2 つの引数が等しいとき NULL を返します。

-- 空文字を NULL として扱う
SELECT NULLIF(name, '') FROM users;

-- 数値の 0 を NULL に
SELECT NULLIF(count, 0) FROM stats;

-- 0 除算回避
SELECT amount / NULLIF(divisor, 0) AS result FROM transactions;

WHERE 句での NULL 判定

CASE 内に限らず、WHERE でも = ではなく IS NULL を使います。

-- NG: 何も返らない
SELECT * FROM users WHERE deleted_at = NULL;

-- OK: 削除されていないユーザー
SELECT * FROM users WHERE deleted_at IS NULL;

-- 削除済みユーザー
SELECT * FROM users WHERE deleted_at IS NOT NULL;

三値論理 — ANDやORの結果

ABA AND BA OR B
trueNULLNULLtrue
falseNULLfalseNULL
NULLNULLNULLNULL

NULL を含む論理演算は「不明」として扱われます。最終的な WHERE 句が NULL になった行は、結果に含まれません。

NOT IN と NULL の落とし穴

-- NULL が含まれる集合に NOT IN すると何も返らない
SELECT * FROM users
WHERE id NOT IN (SELECT user_id FROM ng_list);  -- ng_list に NULL あり → 0 件

-- 対策: NOT EXISTS を使う
SELECT * FROM users u
WHERE NOT EXISTS (
    SELECT 1 FROM ng_list n WHERE n.user_id = u.id
);

CASE 式の 2 つの構文

1. 検索 CASE(推奨)

CASE
    WHEN col1 IS NULL THEN '不明'
    WHEN col1 = 'A' THEN 'アルファ'
    WHEN col1 = 'B' THEN 'ベータ'
    ELSE 'その他'
END

2. 単純 CASE

-- 単純 CASE では NULL を判定できない(= で比較するため)
CASE col1
    WHEN 'A' THEN 'アルファ'
    WHEN 'B' THEN 'ベータ'
    ELSE 'その他'
END

NULL を扱うなら必ず検索 CASEを使いましょう。

FAQ

Q: NULL を含むカラムでソートするとどうなる?
A: ORDER BY における NULL の扱いは RDBMS 依存。NULLS FIRST / NULLS LAST を明示することで制御できます(PostgreSQL / Oracle 等で対応)。

Q: COALESCE と IFNULL のどちらを使うべき?
A: 移植性を考えるなら COALESCE(標準 SQL)。MySQL 専用なら IFNULL でも可。

Q: 集計関数(SUM / COUNT 等)の NULL は?
A: SUM / AVG / MIN / MAX はNULL を無視。COUNT は COUNT(*) なら NULL 行も数え、COUNT(col) なら NULL を除いた行数。

関連

  • CASE式 — 条件分岐の標準構文
  • COALESCE — 最初の非 NULL を返す
  • NVL — Oracle の NULL 置換
  • ISNULL — SQL Server / MySQL の NULL 置換
  • IS NULL — NULL 判定演算子
編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. 基本構文
  2. データベース関連
  3. テーブル関連
  4. ユーザー関連
  5. メタデータ関連
  6. NULL判定を伴うCASE文の使用方法

最近更新/作成されたページ