Q1次のうち、ORDER BY CASE WHEN city = 'Tokyo' THEN 1 WHEN city = 'Osaka' THEN 2 ELSE 9 ENDの説明として正しいものはどれですか。
関数 ⑥ — CASE 応用 — ORDER BY / UPDATE / NULL 対応
この記事は、基礎から複雑なSQL,SQLチューニングまでSQLの実践的なスキルを1からマスターする「SQL入門講座の一部」です。
ORDER BY CASEで任意順序を割り当て、UPDATE SET = CASEで条件付き一括更新、CASEとNULLの落とし穴まで、CSVの社員・顧客データで実行しながら学べます。
本記事で使うデータ — staff と customer
前回まで学んだCASEは SELECT の列リストに置くだけでなく、ORDER BYの中・UPDATEの SET 句にも書ける汎用的な式です。本記事ではこれら 2 つの応用と、CASE で NULL を扱うときの落とし穴を順に押さえます。
題材は前半がstaffテーブル(社員 10 名)、後半がcustomerテーブル(顧客 8 名 / NULL を含む)です。前半はcityを任意順序に並び替え、後半はemailの NULL を「未登録」と表示する CASE、最後にcountryの値を地域カテゴリに書き換えるUPDATE CASEを実行します。
ORDER BY で CASE を使う — 任意の順序を割り当てる
ORDER BYの右辺には列名だけでなく、CASE 式も書けます。これを使うと、文字列のアルファベット順や数値の大小では作れない任意の順序を割り当てられます。「東京 → 大阪 → 京都 → その他」のような業務上の優先順位、「未対応 → 対応中 → 完了」のようなステータス順、ランクの並び順を表現したいときに使います。
書き方はORDER BY CASE WHEN 条件 THEN 数値 ... ELSE 数値 ENDのように、CASE で並び順用の数値を返し、その数値で並べ替えます。ASC(昇順)/ DESC(降順)も列と同じように付けられます。同じ数値の行は、続くORDER BYの 2 番目の列(カンマ区切り)で並ぶので、並び順 + 副キーを組み合わせてカテゴリ内の順序も決められます。
-- 1) city を「Osaka → Kyoto → Tokyo → その他」の順で並べる
SELECT name, city, salary FROM staff
ORDER BY
CASE city
WHEN 'Osaka' THEN 1
WHEN 'Kyoto' THEN 2
WHEN 'Tokyo' THEN 3
ELSE 9
END,
salary DESC; -- 同じ city 内は給料の高い順
-- 2) ORDER BY CASE + DESC で逆順にもできる
-- CASE で 1, 2, 3 と割り当てたなら DESC で 3, 2, 1 の順になる
CASE と NULL の落とし穴 — `= NULL`ではなく`IS NULL`を使う
WHERE と同じく、CASE の中でも= NULL / <> NULLは使えません。NULL との比較結果は常に NULL(不明)になり、CASE の WHEN 句が NULL を返すとその分岐は採用されないため、結果が想定と違ってしまいます。
NULL を判定するときは列 IS NULL / 列 IS NOT NULLを使います。これは前に学んだ WHERE の NULL 判定と同じルールで、CASE / IIF / WHERE / ON など、条件式が書ける場所すべてで共通です。値マッチ形式(CASE 列 WHEN ... THEN)では NULL 判定はできないので、NULL を扱いたいときは必ず評価式形式(CASE WHEN 列 IS NULL THEN ...)を使います。
-- 誤: WHEN NULL では NULL 行を取り出せない('不明' が表示されない)
SELECT name, age,
CASE age
WHEN NULL THEN '不明'
ELSE age
END AS age_display
FROM customer;
-- 正: 評価式形式 + IS NULL
SELECT name, age,
CASE
WHEN age IS NULL THEN '不明'
ELSE age
END AS age_display
FROM customer;
-- 注: COALESCE(age, '不明') でも同じ結果になる
-- 2 値の単純な NULL 置換なら COALESCE の方が簡潔
UPDATE で CASE を使う — 条件に応じて値を書き換える
ここまでは CASE で新しい列を読み取り側で生成していましたが、UPDATEの SET 句に CASE を書くと、テーブル本体の列の値を条件に応じて書き換えることができます。
書き方はUPDATE 表 SET 列 = CASE WHEN 条件 THEN 値1 WHEN 条件 THEN 値2 ... ELSE 列 ENDです。ELSE 列で「どの WHEN にも当てはまらない行は元の値のまま」と書くのが安全な書き方で、これを忘れると ELSE が NULL 扱いになって対象外の行が NULL で上書きされます。
UPDATE はテーブル本体を変更する破壊的な操作なので、本記事では最後の演習で扱います。実行前に同じ条件でSELECT name, 列, CASE ...を試して結果を目視確認し、想定通りなら UPDATE に書き換えるのが本番運用での基本動作です。
-- まず SELECT で結果を確認(NULL の age を 0 にする想定)
SELECT name, age,
CASE
WHEN age IS NULL THEN 0
ELSE age
END AS new_age
FROM customer;
-- 想定どおりなら UPDATE に書き換え
UPDATE customer SET age = CASE
WHEN age IS NULL THEN 0
ELSE age
END;
理解度チェック
まずは1問ずつ答えてみましょう。
Q2次のうち、CASE で NULL を扱う正しい書き方はどれですか。
Q3UPDATE customer SET country = CASE WHEN country IN ('Japan') THEN 'Asia' WHEN country IS NULL THEN 'Unknown' ELSE country END;でELSE countryを書く理由として最も正しいものはどれですか。