Q1次のうち、CASE 式の構造として正しいものはどれですか。
関数 ⑤ — CASE で多条件の分岐表示
SQL の関数記事 5 本目です。CASE 式の 2 つの書き方(値マッチ形式と評価式形式)、3 つ以上の分岐、関数や複合条件、ORDER BY との組み合わせまで、CSV の社員データで動かしながら学べます。
本記事で使うデータ — staff テーブル
前回扱った IIF は条件式が 1 つだけ で、真と偽の 2 値分岐しかできませんでした。本記事の CASE 式 は 3 つ以上の条件 を順に評価して、それぞれに違う値を返せます。SQL の中で「if-elseif-else」を書くための基本構文で、レポートのカテゴリ分け・地域分け・成績ランク分けなど、実務でもっとも頻出する分岐構文です。
題材は前回までと同じ staff テーブル(10 行)です。city 列で地域分類、salary 列で給与帯分類、birthday 列で世代分類を作る演習を通して、CASE の 2 つの書き方と複合条件への応用を順に試します。
CASE には 2 つの書き方がある
CASE 式には 値マッチ形式 と 評価式形式 の 2 通りの書き方があり、どちらも同じ結果を作れます。両方に共通するルールが 2 つあります。
- 最後の `END` が必須 — 書き忘れると構文エラーになります。
- `ELSE` は省略可能 — 省略するとどの
WHENにも一致しない行が NULL になります。NULL を避けたいときはELSEでデフォルト値を明示します。
書き方 ① 値マッチ形式 — 列の値を等価比較する
値マッチ形式は CASE 列 WHEN 値1 THEN 結果1 WHEN 値2 THEN 結果2 ... ELSE デフォルト END と書きます。CASE の直後に 比較したい列を 1 つ 置き、WHEN の右には その列と等しいか調べる値 を書きます。判定は 等価比較(`=`)だけ、WHEN の右に書けるのは 1 つの値だけ で、WHEN ('Tokyo', 'Osaka') のような複数指定はできません。列 = 値 の単純な置き換えに向き、書き方が短くなります。
CASE city が 1 つの列を見て、各 WHEN の値と 等価比較 します。一致した WHEN の THEN の値が返り、どれにも一致しなければ ELSE の値になります。-- 値マッチ形式 — city を地方名に置き換える
SELECT name, city,
CASE city
WHEN 'Tokyo' THEN '関東'
WHEN 'Yokohama' THEN '関東'
WHEN 'Osaka' THEN '関西'
WHEN 'Kyoto' THEN '関西'
ELSE 'その他'
END AS region
FROM staff;
書き方 ② 評価式形式 — 条件式を自由に書く
評価式形式は CASE WHEN 評価式1 THEN 結果1 WHEN 評価式2 THEN 結果2 ... ELSE デフォルト END と書きます。CASE の直後には 何も書かず、各 WHEN の右に 条件式そのもの を置きます。salary >= 6000000 の 比較演算子、name LIKE '%Tanaka' の LIKE、IN、AND / OR の 複合条件 など、WHERE に書ける条件はそのまま使えます。WHEN は 上から順に評価 され、最初に TRUE になった分岐 で値が確定します。表現力が高いため、実務ではこちらを主に使います。
WHEN を 上から順に評価 します。条件が TRUE になったらその THEN の値で確定し、以降は評価しません。FALSE のときは次の WHEN へ下がり、どれも FALSE なら ELSE の値になります。-- 評価式形式 — salary を 2 段階に分ける
SELECT name, salary,
CASE
WHEN salary >= 5000000 THEN '高め'
ELSE '標準'
END AS pay_band
FROM staff;
関数や複合条件と組み合わせて、より複雑な分岐
CASE の WHEN 句には 比較演算子・LIKE・IN・AND / OR・関数呼び出し を組み合わせた評価式を書けます。関数 ① の日付関数で学んだ strftime('%Y', birthday) で生まれ年を取り出して 世代分類 したり、name は『名 姓』の並びなので name LIKE '%Tanaka'(後方一致)で 苗字が Tanaka の人を分類 したり、AND で 複数列を組み合わせた条件 を書いたりできます。
下の例では、生まれ年を 10 年単位で取り出し、1990 年代生まれを 'Z 世代'、1980 年代生まれを 'X/Y 世代' のようにラベル付けします。strftime の戻り値は文字列なので、比較も文字列リテラル('1990' / '1999')と行います。
-- 1) 生まれ年を 5 年区切りでラベル付け
SELECT name, birthday,
CASE
WHEN strftime('%Y', birthday) BETWEEN '1985' AND '1989' THEN '1980 年代後半'
WHEN strftime('%Y', birthday) BETWEEN '1990' AND '1994' THEN '1990 年代前半'
ELSE 'その他'
END AS cohort
FROM staff;
-- 2) 複合条件: 高給かつ Tokyo 在住
SELECT name, city, salary,
CASE
WHEN salary >= 6000000 AND city = 'Tokyo' THEN 'Tokyo シニア'
WHEN salary >= 6000000 THEN 'シニア'
ELSE 'その他'
END AS tag
FROM staff;
理解度チェック
まずは1問ずつ答えてみましょう。
Q2値マッチ形式 CASE city WHEN 'Tokyo' THEN '東京' WHEN 'Osaka' THEN '大阪' ELSE city END の説明として正しいものはどれですか。
Q3CASE WHEN salary >= 6000000 THEN 'シニア' WHEN salary >= 4500000 THEN '中堅' ELSE '若手' END を salary = 7,000,000 の行に対して評価したときの結果はどれですか。