SQLのCASE文とは?条件分岐・NULL・条件付き集計を結果表で解説
CASEは、条件に応じて返す値を変える式です。「CASE文」とも呼ばれますが、SELECTの中では1つの値を作るCASE式として使います。社員5人の表で、月給によって表示する文字や数値を変えてみましょう。
例で使う表
employeesの1行が社員1人分です。salaryは月給(円)で、NULLは未入力を表します。35万円と40万円ちょうどの社員もいるので、条件の境界を確認できます。すべての例でこの5人を使います。結果表の行の並びは一例です。ORDER BYを指定しない場合、表示順は保証されません。
| id(社員ID) | name(名前) | department(部署) | salary(月給) |
|---|---|---|---|
| 1 | 青木 | 営業 | 300000 |
| 2 | 北野 | 開発 | 400000 |
| 3 | 中央 | 営業 | 350000 |
| 4 | 大和 | 開発 | 400000 |
| 5 | 恵比寿 | サポート | NULL |
CASEの基本構文
SELECT name, salary,
CASE
WHEN salary >= 350000 THEN '対象'
ELSE '対象外'
END AS label
FROM employees;WHEN・THEN・ELSE・ENDで表示する値を変える
月給35万円以上なら「対象」、それ以外なら「対象外」を表示します。WHENに条件、THENに条件を満たすときの値、ELSEにそれ以外の値を書き、ENDで閉じます。AS labelは結果の列名です。社員の5行はそのまま残り、判定の列が増えます。NULLの月給は条件がtrueにならないため、ここでは対象外です。
SELECT name, salary,
CASE
WHEN salary >= 350000 THEN '対象'
ELSE '対象外'
END AS label
FROM employees;| name | salary | label |
|---|---|---|
| 青木 | 300000 | 対象外 |
| 北野 | 400000 | 対象 |
| 中央 | 350000 | 対象 |
| 大和 | 400000 | 対象 |
| 恵比寿 | NULL | 対象外 |
WHENを増やして3段階に分ける
40万円以上を「高」、35万円以上40万円未満を「中」、それ以外を「その他」とします。上から最初に成立したWHENの値が採用されるため、40万円以上を先に書きます。北野さんと大和さんは「高」で決まり、中央さんは次の条件で「中」になります。35万円以上を先に書くと、40万円の人も「中」になってしまいます。
SELECT name, salary,
CASE
WHEN salary >= 400000 THEN '高'
WHEN salary >= 350000 THEN '中'
ELSE 'その他'
END AS band
FROM employees;| name | salary | band |
|---|---|---|
| 青木 | 300000 | その他 |
| 北野 | 400000 | 高 |
| 中央 | 350000 | 中 |
| 大和 | 400000 | 高 |
| 恵比寿 | NULL | その他 |
ELSEを省略すると未一致はNULLになる
ELSEを書かずに35万円以上だけに「対象」を付けます。どのWHENにも一致しない青木さんと恵比寿さんの結果はNULLです。CASEがNULLを返しても、その社員の行が消えるわけではありません。行を取り除くWHEREとの違いを結果表で確認してください。
SELECT name, salary,
CASE
WHEN salary >= 350000 THEN '対象'
END AS label
FROM employees;| name | salary | label |
|---|---|---|
| 青木 | 300000 | NULL |
| 北野 | 400000 | 対象 |
| 中央 | 350000 | 対象 |
| 大和 | 400000 | 対象 |
| 恵比寿 | NULL | NULL |
IS NULLで未入力を別の表示にする
未入力の月給をほかの値と区別したい場合は、WHEN salary IS NULLと書きます。恵比寿さんは「未入力」、ほかの4人は「入力済み」です。salary = NULLではtrueにならないため、NULLの確認にはIS NULLを使います。
SELECT name, salary,
CASE
WHEN salary IS NULL THEN '未入力'
ELSE '入力済み'
END AS entry_status
FROM employees;| name | salary | entry_status |
|---|---|---|
| 青木 | 300000 | 入力済み |
| 北野 | 400000 | 入力済み |
| 中央 | 350000 | 入力済み |
| 大和 | 400000 | 入力済み |
| 恵比寿 | NULL | 未入力 |
単純CASEで部署名をコードに変える
同じ列の値を比べるだけなら、CASE departmentの後ろにWHENの候補を書けます。営業をS、開発をD、それ以外をOと表示します。この形は等しいかどうかの比較です。月給の大小やIS NULLのような条件には、これまでのCASE WHEN 条件の形を使います。
SELECT name, department,
CASE department
WHEN '営業' THEN 'S'
WHEN '開発' THEN 'D'
ELSE 'O'
END AS department_code
FROM employees;| name | department | department_code |
|---|---|---|
| 青木 | 営業 | S |
| 北野 | 開発 | D |
| 中央 | 営業 | S |
| 大和 | 開発 | D |
| 恵比寿 | サポート | O |
THEN・ELSEで数値の1と0を返す
CASEは文字列だけでなく数値も返せます。35万円以上なら1、それ以外なら0にすると、北野さん・中央さん・大和さんの3人が1になります。次の節ではこの列を足して人数を求めます。数値の1と0は、シングルクォートで囲まずに書きます。
SELECT name, department, salary,
CASE
WHEN salary >= 350000 THEN 1
ELSE 0
END AS eligible
FROM employees;| name | department | salary | eligible |
|---|---|---|---|
| 青木 | 営業 | 300000 | 0 |
| 北野 | 開発 | 400000 | 1 |
| 中央 | 営業 | 350000 | 1 |
| 大和 | 開発 | 400000 | 1 |
| 恵比寿 | サポート | NULL | 0 |
SUMとCASEで条件に合う人数を集計する
前の1と0を部署ごとにSUMで足します。営業は青木さんの0と中央さんの1で1人、開発は1 + 1で2人、サポートは0人です。WHEREで対象者だけに絞っていないので、対象者が0人のサポートも結果に残ります。GROUP BYを学んでから、この組み合わせを試してみましょう。
SELECT department,
SUM(CASE
WHEN salary >= 350000 THEN 1
ELSE 0
END) AS eligible_people
FROM employees
GROUP BY department;| department | eligible_people |
|---|---|
| 営業 | 1 |
| 開発 | 2 |
| サポート | 0 |
実際に1問解いてみる
CASE・WHEN・THEN・ELSE・END
全社員の全列の末尾にCASEの判定を追加してください。月給350000円以上は「対象」、それ以外(未入力を含む)は「対象外」とします。別名は付けず、行順は問いません。
テーブル
読み込み中…
実行結果
関連構文
CASEについてよくある質問
- CASE文とCASE式は違いますか?
- このガイドで扱うSELECT内のCASEは、条件に応じて1つの値を返す式です。SQLの検索では「CASE文」と呼ばれることもありますが、SQL文全体の実行を分岐する手続き言語の命令とは区別します。
- WHENの条件を複数満たすとどうなりますか?
- 上から最初にtrueになったWHENの値が返ります。40万円以上と35万円以上のように範囲が重なる場合は、優先したい条件を先に書きます。
- CASE salary WHEN NULLで未入力を判定できますか?
- できません。単純CASEは等値比較なのでNULLには一致しません。CASE WHEN salary IS NULL THEN ... ENDの形で判定します。
参考文献
内容はPostgreSQL公式ドキュメントを参照し、初めて学ぶ人向けに日本語で整理しています。
- PostgreSQL公式:CASE — 条件分岐、単純CASE、ELSE省略、返す値の型
- PostgreSQL公式:CASEなどの型解決 — 共通の出力型への変換
- PostgreSQL公式:集約関数 — SUMによる数値の合計