📖 テーマ設定
🔊 音声設定
1.2
1.0
1.0
▶️ 再生コントロール
🎵 BGM設定
0.3
🔔 効果音設定
0.3

NULL/CASE演習

概要

  • 日程: Day 2 / セッション 6
  • 時間: 13:00-13:30
  • 形式: 実習
  • ゴール: CASE式で給与を「高・中・低」に分類するクエリ、NULLを含むデータを正しく扱うクエリをそれぞれ書ける
  • 学習形式: ハンズオン実習(AIペアプログラミング)

導入(5分)

午前中の最後に NULL と CASE を学びました。お昼ごはんを食べている間に、頭はだいぶリセットされたかもしれません。でも大丈夫、午後の最初は手を動かしながら復習する時間です。

今日の演習では、実務でよくある3つのシナリオを扱います:

  • 給与ランク表示(人事担当が報告書を作るイメージ)
  • 電話番号未登録の顧客抽出(マーケが正しい連絡先を補完したいイメージ)
  • NULLを「未登録」と表示する整形(管理画面の見た目を整える)

どれも、現場で「あ、これ研修でやったやつだ」となるシーンです。

本編(10分)

1. 今日使うパターンのおさらい

-- パターン1: CASEで分類
CASE
  WHEN 条件 THEN '高'
  WHEN 条件 THEN '中'
  ELSE  '低'
END AS rank

-- パターン2: NULLの判定
WHERE phone IS NULL
WHERE phone IS NOT NULL

-- パターン3: NULLの置き換え
COALESCE(phone, '未登録')

2. 演習で見ておきたいこと

CASEの結果に列名(エイリアス)を付ける AS の位置、COALESCE で代替値が文字列であること、WHEREで NULL を扱うときの IS NULL の感覚——この3つを、コードを書きながら指に覚えさせるのが今日の目標です。

💬 AIに聞いてみよう

  • 「CASEで4段階以上に分類するときの書き方の見本を出して」
  • 「COALESCE と CASE、どちらで書くべきかの判断軸は?」
  • 「NULL を含む列で件数を数えたいとき、COUNT(*) と COUNT(列名) どっち?」

実習・演習(15分)

課題

課題1: 給与ランクで分類する

employees 全員について、給与を以下の3段階に分類して表示してください。

  • 高: 500,000 円以上
  • 中: 400,000 円以上 500,000 円未満
  • 低: それ未満

期待する列:first_name, last_name, salary, salary_rank、給与降順で並べる。

SELECT first_name,
       last_name,
       salary,
       CASE
         WHEN salary >= 500000 THEN '高'
         WHEN salary >= 400000 THEN '中'
         ELSE '低'
       END AS salary_rank
FROM employees
ORDER BY salary DESC;

実行結果から、「高」「中」「低」がそれぞれ何人いるか数えてみてください。

課題2: ランクごとの人数を集計する

課題1のCASE式を GROUP BY と組み合わせて、ランクごとの人数を出してください。

SELECT CASE
         WHEN salary >= 500000 THEN '高'
         WHEN salary >= 400000 THEN '中'
         ELSE '低'
       END AS salary_rank,
       COUNT(*) AS 人数
FROM employees
GROUP BY salary_rank
ORDER BY 人数 DESC;

課題3: 電話番号が未登録の顧客を探す

customers テーブルの phone は、サンプルデータでは全件埋まっています。まずは BEGIN してNULL を作ってみましょう。

BEGIN;

-- 1件をわざと NULL にする
UPDATE customers SET phone = NULL WHERE customer_id = 1;

-- 確認1: 等価比較は機能しない(0件になる)
SELECT customer_id, customer_name, phone
FROM customers
WHERE phone = NULL;

-- 確認2: IS NULL を使うと取れる
SELECT customer_id, customer_name, phone
FROM customers
WHERE phone IS NULL;

ROLLBACK;

phone = NULL だと0件、IS NULL だと取れる」——この違いを目で確認するのが今日のヤマです。

課題4: NULL を「未登録」と表示する

引き続きBEGINしてphoneにNULLを作り、COALESCEで整形した一覧を作ってください。

BEGIN;
UPDATE customers SET phone = NULL WHERE customer_id IN (1, 3);

SELECT customer_id,
       customer_name,
       COALESCE(phone, '未登録') AS phone_display
FROM customers
ORDER BY customer_id;

ROLLBACK;

8件のうち2件が「未登録」と表示されることを確認。

課題5: CASE で書き換える

課題4と同じ結果を、COALESCE ではなく CASE 式で書いてみてください。

BEGIN;
UPDATE customers SET phone = NULL WHERE customer_id IN (1, 3);

SELECT customer_id,
       customer_name,
       CASE
         WHEN phone IS NULL THEN '未登録'
         ELSE phone
       END AS phone_display
FROM customers
ORDER BY customer_id;

ROLLBACK;

「COALESCE と CASE、どちらが好みか」を考えてみてください。シンプルなら COALESCE、条件が増えるなら CASE が向いている、と感じられるはずです。

課題6(チャレンジ): 注文ステータスを日本語化する

orders.status'pending''processing''shipped''completed' のいずれかです。これを日本語に置き換えて表示してください。

SELECT order_id,
       order_date,
       CASE status
         WHEN 'pending'    THEN '未処理'
         WHEN 'processing' THEN '処理中'
         WHEN 'shipped'    THEN '発送済'
         WHEN 'completed'  THEN '完了'
         ELSE '不明'
       END AS 状態
FROM orders
ORDER BY order_date;

CASEには上の「単純CASE」(CASE 列 WHEN 値 ...)と、CASE WHEN 条件 ... の2形式があります。今回のように値の置き換えなら単純CASEがすっきり書けます。

成果物

以下を1ファイルにまとめてください。

  • 課題1〜5の実行SQLと結果(先頭5行ずつでOK)
  • 課題3で phone = NULL の結果が0件だった理由(1行で)
  • 課題4と課題5を比べて、自分はどちらの書き方が好きか、その理由

ヒント

  • BEGIN を打ったまま課題を進めて、終わったら ROLLBACK で元に戻すのが安全
  • AIに「このCASE式を日本語で順番に説明して」と頼むと、自分の理解確認になる
  • CASEの条件は上から順に評価される。「高」を salary >= 400000 より先に置かないと「中」「高」が混ざる

まとめ(5分)

NULL と CASE は、データを「正直に扱い」「見やすく加工する」ための2つの基本ツールです。IS NULLCOALESCECASE WHEN——この3つを反射的に出せれば、レポート作成系のクエリで困ることはまずありません。

今日はDay2の前半(INSERT/UPDATE/DELETE → JOIN → NULL/CASE)が一区切りです。データを変える・つなぐ・整える、の3点セットが揃いました。

次のセッション以降では、サブクエリやビュー、テーブル設計・制約、最後にインデックスとトランザクションへと進みます。今日学んだことが、その全部の土台になります。

🔄 振り返りチェック

  • なぜ phone = NULL ではダメで、IS NULL でなければならないのですか?
  • COALESCE と CASE はどう使い分けますか?
  • CASEで分類するとき、条件の順序を間違えるとどうなりますか?

補足資料

  • 発展課題: 「営業部の社員だけ給与ランクを表示し、それ以外は『対象外』と出す」というクエリを書いてみる(CASEとJOINを組み合わせる)

学習ガイド

想定される質問と回答例

質問 ヒント
CASEの結果を ORDER BY に使える? 使える。ORDER BY CASE WHEN status='pending' THEN 1 ELSE 2 END のように並び順を作れる
ELSE を書かなかったら? マッチしない行は NULL になる。意図せず NULL が混ざるので、明示的に書くのを推奨
GROUP BY にCASEの列名(エイリアス)を書ける? PostgreSQL では書ける(標準SQLだと位置番号や式の再記述が必要な場合あり)。エイリアスを使うとシンプル
phone <> '03-1234-5678' で NULL の人を含めたいときは? WHERE phone <> '03-1234-5678' OR phone IS NULL のように OR で足す。NULLは比較に勝てないので明示的に拾う

つまずきやすいポイント

つまずきポイント ヒント
CASEの条件順序を逆にして全部「中」になる 上から順にマッチするので、厳しい条件(高)→ 緩い条件(中)→ ELSE(低)の順で書く
WHERE phone = NULL で件数0、そして「データがない!」と勘違い NULL の比較は NULL になり、TRUE じゃないので WHERE から落ちる。必ず IS NULL
CASE式に END を付け忘れる 構文エラーで止まる。「CASE …… END AS 列名」と覚える
COALESCEの第2引数の型がズレる 文字列と数値を混ぜると型エラー。NULL を文字列に置き換えるなら代替値も文字列
読み上げを開始します...

AIに質問する