もしもうCASEに慣れてたら、ロジックを直接クエリに埋め込む方法って知ってるよね。でもCASEには2つの形があるって意外と知られてない。CASE WHEN ...はif-elseみたいな条件分岐だけど、シンプルなCASEは他の言語のswitch-caseみたいな感じ:1つの式を複数の値と比べて、合うやつのブロックを実行するんだ。
1つのカラムを固定値と比べる時は、こっちの方がコンパクトで直感的。
シンプルなCASEの構文
CASE expression
WHEN value1 THEN result1
WHEN value2 THEN result2
...
ELSE default_result
END
めっちゃシンプル:
expression— これは比べる式やカラム。value1、value2とかと比べる。THENは一致した時に返すやつ。ELSE— どれも合わなかった時に返すやつ(省略できるけど、入れた方がいい)。
例:学生の成績
studentsテーブルにgradeカラムがあって、2から5までの整数が入ってるとしよう。これをテキストで表示したい時:
SELECT
name,
grade,
CASE grade
WHEN 5 THEN '優秀'
WHEN 4 THEN '良い'
WHEN 3 THEN '可'
WHEN 2 THEN '不可'
ELSE '不明'
END AS 成績_テキスト
FROM students;
ここでCASEはgradeカラムの値を2, 3, 4, 5と比べてる。
例:商品カテゴリをコードから表示
productsテーブルのcategory_codeカラムには'el'、'frn'、'bks'みたいな短いラベルが入ってる。読みやすいカテゴリ名を表示したい時:
SELECT
product_name,
category_code,
CASE category_code
WHEN 'el' THEN 'エレクトロニクス'
WHEN 'frn' THEN '家具'
WHEN 'bks' THEN '本'
ELSE 'その他'
END AS category_name
FROM products;
こういうのは、「人間向け」テキストをコードの代わりに出したい時に超便利。
例:月の名前
月番号からテキストで月名を出したい時:
SELECT
EXTRACT(MONTH FROM order_date) AS month_number,
CASE EXTRACT(MONTH FROM order_date)
WHEN 1 THEN '1月'
WHEN 2 THEN '2月'
WHEN 3 THEN '3月'
WHEN 4 THEN '4月'
WHEN 5 THEN '5月'
WHEN 6 THEN '6月'
WHEN 7 THEN '7月'
WHEN 8 THEN '8月'
WHEN 9 THEN '9月'
WHEN 10 THEN '10月'
WHEN 11 THEN '11月'
WHEN 12 THEN '12月'
ELSE '不明'
END AS month_name
FROM orders;
シンプルなCASEで、1〜12の数字を一発で分かりやすくできる。
シンプルなCASEでのNULLの扱い
大事なのは、値がNULLと比べられる時、結果はNULLになるってこと。なぜならNULL = NULLは真じゃなくて、不明だから。
NULLの例:
SELECT
user_id,
status,
CASE status
WHEN 'active' THEN 'アクティブ'
WHEN 'blocked' THEN 'ブロック済み'
WHEN NULL THEN 'ステータスなし' -- これは効かない!
ELSE '不明'
END AS user_state
FROM users;
WHEN NULLの代わりにELSEを使うか、検索型CASE(前回のレクチャーでやったやつ)を使おう:
CASE
WHEN status IS NULL THEN 'ステータスなし'
...
検索型CASEとの比較
| 特徴 | シンプルCASE | 検索型CASE |
|---|---|---|
| 特定の値との比較 | ✅ 得意 | ❌ 不向き |
| 柔軟な条件(>, IS NULLなど) | ❌ 無理 | ✅ できる |
| プログラミングでの類似 | switch-case |
if-else |
実用ケース
例:リクエストのステータス可視化
| request_id | status |
|---|---|
| 101 | new |
| 102 | in_progress |
| 103 | done |
| 104 | cancelled |
| 105 | NULL |
SELECT
request_id,
CASE status
WHEN 'new' THEN '🟡 新規'
WHEN 'in_progress' THEN '🔵 進行中'
WHEN 'done' THEN '🟢 完了'
ELSE '⚪ 不明'
END AS status_label
FROM requests;
| request_id | status_label |
|---|---|
| 101 | 🟡 新規 |
| 102 | 🔵 進行中 |
| 103 | 🟢 完了 |
| 104 | ⚪ 不明 |
| 105 | ⚪ 不明 |
ここでCASEは翻訳者みたいな役割:テクニカルなステータスを分かりやすく(しかも可愛い)ラベルに変換。ステータスが不明やNULLでも、ユーザーには⚪「不明」って出る。
例:レポート用のカテゴリ分け
| employee_id | name | department |
|---|---|---|
| 1 | Alex Lin | HR |
| 2 | Maria Chi | IT |
| 3 | Anna Song | IT |
| 4 | Otto Art | FIN |
| 5 | Jane Doe | HR |
| 6 | Max Gray | SALES |
| 7 | Zoe Black | IT |
| 8 | Tom Brown | FIN |
| 9 | Liam Park | NULL |
| 10 | Eva Gold | HR |
SELECT
CASE department
WHEN 'HR' THEN '人事'
WHEN 'IT' THEN 'テクノロジー'
WHEN 'FIN' THEN '財務'
ELSE 'その他'
END AS dept_name,
COUNT(*) AS staff_count
FROM employees
GROUP BY
CASE department
WHEN 'HR' THEN '人事'
WHEN 'IT' THEN 'テクノロジー'
WHEN 'FIN' THEN '財務'
ELSE 'その他'
END;
結果:
| dept_name | staff_count |
|---|---|
| 人事 | 3 |
| テクノロジー | 3 |
| 財務 | 2 |
| その他 | 2 |
何が起きてるかというと:
- HRの人は「人事」カテゴリに入る。
- ITは「テクノロジー」。
- FINは「財務」。
- それ以外(SALESやNULLも含む)は「その他」。こういうやり方は、フレンドリーで分かりやすいレポート作りにピッタリ。
よくあるミス
ELSEを忘れる → どれも一致しなかったらNULLになる。NULLと比較する → 効かないから、IS NULLと検索型CASEを使おう。- 型が合わないものを比べる → 例えば
gradeが数値型なのにCASE grade WHEN '5'みたいに書く。
シンプルなCASEは、1つの値をいくつかの候補と比べたい時の武器。コンパクトで読みやすくて、テキスト分類や可視化、コード変換、グループ化に超便利。
もし範囲チェックやNULL、もっと複雑な条件が必要なら、検索型CASEを使おう。SQLは分かりやすさが命。CASEは、その分かりやすさを形にするためのツールだよ。
GO TO FULL VERSION