SQL練習室
← SQLガイド

SQLのCASE文とは?条件分岐・NULL・条件付き集計を結果表で解説

CASEは、条件に応じて返す値を変える式です。「CASE文」とも呼ばれますが、SELECTの中では1つの値を作るCASE式として使います。社員5人の表で、月給によって表示する文字や数値を変えてみましょう。

例で使う表

employeesの1行が社員1人分です。salaryは月給(円)で、NULLは未入力を表します。35万円と40万円ちょうどの社員もいるので、条件の境界を確認できます。すべての例でこの5人を使います。結果表の行の並びは一例です。ORDER BYを指定しない場合、表示順は保証されません。

employees:社員5人の一覧(salaryは月給・円)
id(社員ID)name(名前)department(部署)salary(月給)
1青木営業300000
2北野開発400000
3中央営業350000
4大和開発400000
5恵比寿サポートNULL

CASEの基本構文

sql
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にならないため、ここでは対象外です。

sql
SELECT name, salary,
  CASE
    WHEN salary >= 350000 THEN '対象'
    ELSE '対象外'
  END AS label
FROM employees;
実行結果
namesalarylabel
青木300000対象外
北野400000対象
中央350000対象
大和400000対象
恵比寿NULL対象外

WHENを増やして3段階に分ける

40万円以上を「高」、35万円以上40万円未満を「中」、それ以外を「その他」とします。上から最初に成立したWHENの値が採用されるため、40万円以上を先に書きます。北野さんと大和さんは「高」で決まり、中央さんは次の条件で「中」になります。35万円以上を先に書くと、40万円の人も「中」になってしまいます。

sql
SELECT name, salary,
  CASE
    WHEN salary >= 400000 THEN '高'
    WHEN salary >= 350000 THEN '中'
    ELSE 'その他'
  END AS band
FROM employees;
実行結果
namesalaryband
青木300000その他
北野400000高
中央350000中
大和400000高
恵比寿NULLその他

ELSEを省略すると未一致はNULLになる

ELSEを書かずに35万円以上だけに「対象」を付けます。どのWHENにも一致しない青木さんと恵比寿さんの結果はNULLです。CASEがNULLを返しても、その社員の行が消えるわけではありません。行を取り除くWHEREとの違いを結果表で確認してください。

sql
SELECT name, salary,
  CASE
    WHEN salary >= 350000 THEN '対象'
  END AS label
FROM employees;
実行結果
namesalarylabel
青木300000NULL
北野400000対象
中央350000対象
大和400000対象
恵比寿NULLNULL

IS NULLで未入力を別の表示にする

未入力の月給をほかの値と区別したい場合は、WHEN salary IS NULLと書きます。恵比寿さんは「未入力」、ほかの4人は「入力済み」です。salary = NULLではtrueにならないため、NULLの確認にはIS NULLを使います。

sql
SELECT name, salary,
  CASE
    WHEN salary IS NULL THEN '未入力'
    ELSE '入力済み'
  END AS entry_status
FROM employees;
実行結果
namesalaryentry_status
青木300000入力済み
北野400000入力済み
中央350000入力済み
大和400000入力済み
恵比寿NULL未入力

単純CASEで部署名をコードに変える

同じ列の値を比べるだけなら、CASE departmentの後ろにWHENの候補を書けます。営業をS、開発をD、それ以外をOと表示します。この形は等しいかどうかの比較です。月給の大小やIS NULLのような条件には、これまでのCASE WHEN 条件の形を使います。

sql
SELECT name, department,
  CASE department
    WHEN '営業' THEN 'S'
    WHEN '開発' THEN 'D'
    ELSE 'O'
  END AS department_code
FROM employees;
実行結果
namedepartmentdepartment_code
青木営業S
北野開発D
中央営業S
大和開発D
恵比寿サポートO

THEN・ELSEで数値の1と0を返す

CASEは文字列だけでなく数値も返せます。35万円以上なら1、それ以外なら0にすると、北野さん・中央さん・大和さんの3人が1になります。次の節ではこの列を足して人数を求めます。数値の1と0は、シングルクォートで囲まずに書きます。

sql
SELECT name, department, salary,
  CASE
    WHEN salary >= 350000 THEN 1
    ELSE 0
  END AS eligible
FROM employees;
実行結果
namedepartmentsalaryeligible
青木営業3000000
北野開発4000001
中央営業3500001
大和開発4000001
恵比寿サポートNULL0

SUMとCASEで条件に合う人数を集計する

前の1と0を部署ごとにSUMで足します。営業は青木さんの0と中央さんの1で1人、開発は1 + 1で2人、サポートは0人です。WHEREで対象者だけに絞っていないので、対象者が0人のサポートも結果に残ります。GROUP BYを学んでから、この組み合わせを試してみましょう。

sql
SELECT department,
  SUM(CASE
    WHEN salary >= 350000 THEN 1
    ELSE 0
  END) AS eligible_people
FROM employees
GROUP BY department;
実行結果
departmenteligible_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公式ドキュメントを参照し、初めて学ぶ人向けに日本語で整理しています。