SQL CASE WHEN文:条件分岐を使いこなす基本構文
SQLでデータを扱う際、特定の条件に基づいて異なる値を返したい場面は頻繁にあります。
例えば、顧客の購入金額に応じて「一般」「プレミアム」「VIP」といったランクを付けたい場合や、テストの点数に応じて「優」「良」「可」「不可」といった評価を割り当てたい場合などです。
このような、いわゆる「もし~ならば~、そうでなければ~」といった条件分岐をSQLクエリの中で実現するにはどうすれば良いのでしょうか?
今回は、SQLにおける条件分岐の基本となるCASE WHEN文について、その構文と使い方を詳しく見ていきましょう。
CASE WHEN文の基本構文
CASE WHEN文は、SQLで条件分岐を行うための標準的な方法です。
その基本的な構文は以下のようになります。
CASE
WHEN 条件1 THEN 結果1
WHEN 条件2 THEN 結果2
...
ELSE デフォルト結果
END
この構文は、IF-THEN-ELSE文に似ています。
CASEキーワードで条件分岐の開始を宣言します。WHENキーワードに続けて条件式を指定します。THENキーワードに続けて、その条件が満たされた場合に返したい結果を指定します。- 複数の
WHEN節を連ねることで、複数の条件を順番に評価できます。 - どの
WHEN節の条件も満たされなかった場合に返されるデフォルトの結果は、ELSEキーワードに続けて指定します。 ELSE節は省略可能ですが、省略した場合、どのWHEN節の条件も満たされなかった場合はNULLが返されます。ENDキーワードで条件分岐の終了を宣言します。
このCASE WHEN文は、SELECT文のリスト、WHERE句、ORDER BY句など、SQLの様々な場所で使用できます。
具体的な使い方と例
それでは、CASE WHEN文がどのように使われるのか、具体的な例を見ていきましょう。
例1:顧客の購入金額に応じたランク付け
customersテーブルにpurchase_amount(購入金額)という列があると仮定します。
この購入金額に応じて、顧客を「一般」「プレミアム」「VIP」の3つのランクに分けたいとします。
- 購入金額が10,000円以上なら「VIP」
- 購入金額が5,000円以上10,000円未満なら「プレミアム」
- それ以外なら「一般」
この条件をCASE WHEN文で表現すると、以下のようになります。
SELECT
customer_id,
purchase_amount,
CASE
WHEN purchase_amount >= 10000 THEN 'VIP'
WHEN purchase_amount >= 5000 THEN 'プレミアム'
ELSE '一般'
END AS customer_rank
FROM
customers;
このクエリを実行すると、各顧客のcustomer_id、purchase_amountに加えて、計算されたcustomer_rankが表示されます。
実行結果の例:
| customer_id | purchase_amount | customer_rank |
|---|---|---|
| 1 | 12000 | VIP |
| 2 | 6500 | プレミアム |
| 3 | 3000 | 一般 |
| 4 | 15000 | VIP |
| 5 | 7000 | プレミアム |
CASE WHEN文は、SELECTリスト内で新しい列(この例ではcustomer_rank)を作成するのに非常に便利です。
例2:テストの点数による成績評価
scoresテーブルにscore(点数)という列があるとします。
点数に応じて成績を評価するCASE WHEN文を作成してみましょう。
- 80点以上なら「優」
- 60点以上80点未満なら「良」
- 40点以上60点未満なら「可」
- それ未満なら「不可」
SELECT
student_id,
score,
CASE
WHEN score >= 80 THEN '優'
WHEN score >= 60 THEN '良'
WHEN score >= 40 THEN '可'
ELSE '不可'
END AS grade
FROM
scores;
このクエリでは、score列の値に基づいてgrade列が計算されます。
CASE WHEN文は、条件が上から順に評価されるため、条件の順番が重要になります。
例えば、上記の例でWHEN score >= 40 THEN '可'という条件をWHEN score >= 80よりも前に記述してしまうと、80点以上の点数もすべて「可」と評価されてしまい、意図しない結果になります。
常に、より具体的な条件や、より高い値(または低い値)を求める条件を先に記述するように心がけましょう。
例3:NULL値の扱い
ordersテーブルにshipped_date(出荷日)という列があり、まだ出荷されていない注文ではNULLが入っているとします。
出荷日を元に、注文のステータスを「出荷済み」「未出荷」と表示したい場合、ELSE節でNULLを処理するのが一般的です。
SELECT
order_id,
order_date,
shipped_date,
CASE
WHEN shipped_date IS NOT NULL THEN '出荷済み'
ELSE '未出荷'
END AS order_status
FROM
orders;
この例では、shipped_dateがNULLでない場合に「出荷済み」、NULLの場合に「未出荷」と表示されます。
IS NOT NULLやIS NULLといった比較演算子は、NULL値を扱う際によく使われます。
NULLは他の値とは異なり、=や!=といった比較演算子で直接比較できません。
そのため、NULLかどうかを判定するにはIS NULLまたはIS NOT NULLを使用する必要があります。
例4:WHERE句でのCASE WHEN文の使用
CASE WHEN文はWHERE句でも利用できます。
例えば、特定の部署(例: 'Sales')に所属する従業員のうち、is_manager(役職フラグ)が1である者のみを抽出したい場合などに使えます。
SELECT
employee_id,
department,
is_manager
FROM
employees
WHERE
CASE
WHEN department = 'Sales' THEN is_manager
ELSE 0 -- 他の部署の場合は、抽出条件を満たさないようにする
END = 1;
この例では、departmentが'Sales'の場合にis_managerの値が評価され、それ以外の場合は0が返されるため、結果的に'Sales'部署でis_managerが1の従業員のみが抽出されます。
しかし、WHERE句でCASE WHEN文を使うのは、条件が複雑になりがちで、可読性が低下する可能性があります。
多くの場合、WHERE句で複数の条件をANDやORで組み合わせる方が、よりシンプルで理解しやすいクエリになります。
例えば、上記の例は以下のように書き換える方が一般的です。
SELECT
employee_id,
department,
is_manager
FROM
employees
WHERE
department = 'Sales'
AND is_manager = 1;
CASE WHEN文をWHERE句で使うのは、特定の状況下でのみ検討するのが良いでしょう。
CASE WHEN文の応用と注意点
CASE WHEN文は非常に柔軟で、様々な場面で活用できます。
集計関数との組み合わせ
CASE WHEN文は、SUMやCOUNTといった集計関数と組み合わせて使用することで、さらに強力な分析が可能になります。
例えば、ordersテーブルから、特定の期間における「出荷済み」と「未出荷」の注文数をそれぞれカウントしたい場合を考えてみましょう。
SELECT
COUNT(CASE WHEN shipped_date IS NOT NULL THEN 1 ELSE NULL END) AS shipped_count,
COUNT(CASE WHEN shipped_date IS NULL THEN 1 ELSE NULL END) AS pending_count
FROM
orders
WHERE
order_date BETWEEN '2023-01-01' AND '2023-12-31';
このクエリでは、CASE WHEN文を使って各行が出荷済みか未出荷かを判定し、その結果をCOUNT関数で集計しています。
COUNT()関数は、NULL以外の値をカウントするため、CASE WHENで1を返した行のみがカウントされます。
このように、CASE WHENと集計関数を組み合わせることで、条件に応じたクロス集計のような結果を簡単に得ることができます。
CASE WHEN文の落とし穴
CASE WHEN文を使う上で注意すべき点がいくつかあります。
- 条件の順序: 先述の通り、
WHEN節の条件は上から順に評価されます。意図した結果を得るためには、条件の順序を慎重に決定する必要があります。 - NULL値の扱い:
NULL値の比較にはIS NULLまたはIS NOT NULLを使用します。 - データ型の一貫性:
THEN節やELSE節で返される値は、すべて同じデータ型であるか、互換性のあるデータ型である必要があります。 例えば、あるTHEN節で数値を返し、別のTHEN節で文字列を返すと、エラーになるか、予期しない型変換が発生する可能性があります。 - ELSE節の省略:
ELSE節を省略した場合、どの条件にも一致しない行はNULLを返します。意図しないNULL値の発生を防ぐために、ELSE節を明示的に記述することを推奨します。
まとめ
CASE WHEN文は、SQLで条件分岐を行うための非常に強力で柔軟な構文です。
顧客ランク付け、成績評価、ステータス表示など、様々な場面でデータを加工し、より分かりやすく表現するために不可欠な機能と言えるでしょう。
今回紹介した基本構文と例を参考に、ぜひご自身のSQLクエリでCASE WHEN文を活用してみてください。
集計関数との組み合わせや、WHERE句での利用など、応用範囲は広いです。
SQL Questでは、これからも皆様のSQL学習をサポートする記事をお届けしていきます。