NULL値の扱いとCASE式
概要
- 日程: Day 2 / セッション 5
- 時間: 11:40-12:00
- 形式: 座学
- ゴール: NULLが「未知の値」であり通常の比較で扱えないことと、CASE式による条件分岐の書き方を説明できる
- 学習形式: 対話型解説
導入(5分)
前のJOIN演習で、LEFT JOIN の結果に NULL が出てきたのを覚えていますか? 「総務部 / 社員なし」の行で、first_name が NULL になっていました。
NULL は SQLの中でとびきり厄介な存在です。なぜなら「0でも空文字でもなく、未知」だからです。「未知」をどう扱うか——これを誤ると、件数がズレたり、フィルタから漏れたりします。
このセッションでは、NULL の正体と、結果を「高・中・低」のように分類する CASE式 を学びます。
本編(15分)
1. NULL は「ゼロ」でも「空文字」でもない
たとえば顧客テーブルに、電話番号未登録の顧客がいるとします。phone 列には何が入るでしょうか?
- 0 を入れる → 0番という電話番号があることになる(嘘)
- 空文字
''を入れる → 「番号は空文字です」という主張(これも嘘) - NULL を入れる → 「番号は分からない/未登録」という正直な表明
NULL は「値が分からない、未知である」というマーカーです。
コード例・実例
SELECT customer_name, phone
FROM customers
WHERE phone IS NULL;
ここで気をつけたいのが、phone = NULL と書いてはいけないこと。
-- これは結果が0件になる(意図と違う)
SELECT * FROM customers WHERE phone = NULL;
理由は、「未知 = 未知」が真にならないからです。NULL同士の比較は 常に NULL(不明) という第3の真理値になり、WHERE は TRUE の行しか返さないので、結果から落ちます。
たとえるなら「中身の分からない箱A」と「中身の分からない箱B」を比べて「同じです」と断言できますか? できませんよね。それと同じです。
2. NULL を扱う3兄弟
| 演算子 | 意味 |
|---|---|
IS NULL |
NULL かどうかを判定 |
IS NOT NULL |
NULL でないかを判定 |
COALESCE(列, 代替値) |
NULL なら代替値に置き換える |
コード例・実例
電話番号が未登録の顧客を抽出:
SELECT customer_name
FROM customers
WHERE phone IS NULL;
未登録なら「未登録」と表示する:
SELECT customer_name, COALESCE(phone, '未登録') AS phone
FROM customers;
ここがポイント
=ではなくIS NULLを使う(鉄則)COALESCEは引数を左から見て、最初に NULL でないものを返す- COALESCE は何個でも書ける:
COALESCE(a, b, c, '不明')のように
コラム — 「NULL同士は等しくない」事件
ある集計バッチで、「同じ商品コードの注文をまとめる」処理を書いた人が、商品コードに NULL が混ざっていたためにグループ化されない問題に遭遇しました。NULL は他のNULLと等しいと見なされないので、GROUP BY product_code で NULL の行が一つずつ別グループになりかけて、集計件数が増えて大慌て。SQLでは「NULL は誰の友達でもない」と覚えてください。
3. CASE式 — SQLの中の if 文
「給与が高い/中/低を判定して表示したい」——これがCASE式の出番です。
コード例・実例
SELECT first_name,
last_name,
salary,
CASE
WHEN salary >= 500000 THEN '高'
WHEN salary >= 400000 THEN '中'
ELSE '低'
END AS salary_rank
FROM employees;
結果:
| first_name | last_name | salary | salary_rank |
|---|---|---|---|
| 太郎 | 山田 | 450000 | 中 |
| 花子 | 鈴木 | 520000 | 高 |
| ... | ... | ... | ... |
基本構文:
CASE
WHEN 条件1 THEN 値1
WHEN 条件2 THEN 値2
ELSE デフォルト値
END
ここがポイント
- 上から順に評価され、最初にマッチした WHEN で確定する
ELSEを書かないとマッチしないときに NULL になる- 最後に
ENDを忘れない(PostgreSQLのendは予約語的に区切りを意味する) - 結果に列名を付けたいときは
END AS 列名
4. CASE と NULL の組み合わせワザ
NULL を判定して、結果を分けたいケース。
SELECT customer_name,
CASE
WHEN phone IS NULL THEN '未登録'
ELSE phone
END AS phone_display
FROM customers;
これは前に出てきた COALESCE(phone, '未登録') と同じ意味です。シンプルな置き換えは COALESCE、複雑な条件分岐は CASE と使い分けます。
💬 AIに聞いてみよう
- 「NULL を含む列の合計や平均をとると、どう扱われる?」
- 「CASE と COALESCE はどちらを使うべき?選び方を教えて」
- 「
CASE salary WHEN 500000 THEN ...のような書き方もあるって本当?」
まとめ(5分)
NULL は「未知」のマーカー。比較には = ではなく IS NULL を使い、置き換えたいときは COALESCE を使う——これだけで、ほとんどのNULLトラブルは避けられます。
CASE式は SQL の中の if 文。CASE WHEN ... THEN ... ELSE ... END の構造を覚えておけば、結果の見た目を整えたり、レポート用の分類を作ったりが自在になります。
次のセッション(昼休み後)では、これらを使って実際に「給与ランク表示」「電話未登録の顧客抽出」「未登録の見た目を整える」演習を行います。
🔄 振り返りチェック
phone = NULLとphone IS NULLの違いを説明できますか?- COALESCE と CASE の使い分けを言えますか?
- CASE式の最後に書く
ENDを忘れたら何が起きますか?
補足資料
- 発展課題: 自分の身の回りで「未入力」をどう表現するか考えてみる(例:申込書の任意欄、SNSのプロフィール)。NULL/空文字/既定値のどれが適切か?
学習ガイド
想定される質問と回答例
| 質問 | ヒント |
|---|---|
| NULL を含む列を SUM や AVG したら? | NULL は計算から除外される。SUM(salary) は NULL を無視して残りを足す。COUNT(*) は NULL も含むが COUNT(列名) は NULL を除外する |
WHERE phone <> '03-1234-5678' で NULL の人は出てくる? |
出てこない。NULL との比較は NULL になり、TRUE 以外は WHERE から落ちる。「NULL も含めて他」が欲しいなら OR phone IS NULL を足す |
| COALESCE と NULLIF の違いは? | COALESCE はNULLを別の値に置き換える。NULLIF(a, b) は a=b のとき NULL を返す(逆方向の変換) |
| CASE は WHERE や ORDER BY でも使える? | 使える。ORDER BY CASE WHEN status = 'pending' THEN 1 ELSE 2 END のように並び順を制御するのもよくある |
つまずきやすいポイント
| つまずきポイント | ヒント |
|---|---|
column = NULL と書いてしまう |
必ず IS NULL / IS NOT NULL。プログラミング言語のクセが出やすいので注意 |
| NULL が混じった列で集計件数が合わない | COUNT(*) は全行、COUNT(列名) は NULL を除外。意図に合わせて使い分ける |
CASE で ELSE を書かず、想定外に NULL になる |
マッチしないと結果は NULL。ELSE を書く習慣を |
CASE の END を書き忘れる/AS の位置を間違える |
... ELSE 値 END AS 列名 の順序。END を忘れると構文エラーで止まる |