【SQL】 CASE式の基本構文から実践例まで徹底解説!

【SQL】 CASE式の基本構文 から実践例まで データベース
スポンサーリンク

はじめに

ぴんくうさぎ
ぴんくうさぎ

CASE式がなかなか理解できないよ〜

みどりがめ
みどりがめ

CASE式は初心者が躓きやすい分野の一つだね。

今回はCASE式の基本から実践例まで解説していくよ!

CASE式とは?

CASE式は、SQLで条件に基づいて処理を分岐させるための仕組みです。これをイメージする際に、「もし〜ならば〜、それ以外ならば〜」という形で考えると理解しやすいです。

例えば、従業員の給与に応じてランクをつける場合を考えましょう。
給与が100万以上なら「高給」、50万以上なら「中給」、それ以下なら「低給」というようにランクづけしたいとします。その時にCASE式を使います。

CASE式の基本構文

単純CASE式と検索CASE式

CASE式には「単純CASE式」「検索CASE式」の大きく二つの書き方があります。

-- 単純CASE式
CASE fruit_id
	WHEN '1' THEN 'りんご'
	WHEN '2' THEN 'みかん'
	WHEN '3' THEN 'バナナ'
ELSE 'その他' END
-- 検索CASE式
CASE 
	WHEN fruit_id = '1' THEN 'りんご'
	WHEN fruit_id = '2' THEN 'みかん'
	WHEN fruit_id = '3' THEN 'バナナ'
ELSE 'その他' END

上記はどちらも同じ動きをします。フルーツのIDをもとにフルーツ名を読み分けています。
単純CASE式の方が、可読性は高いです。一方で使える場面が限られているので、基本的には検索CASE式で覚えると良いでしょう。

CASE式を使う上での注意事項

  • ENDの書き忘れ
    →慣れないうちはやりがちです。文法エラーになります。
  • ELSE句は書くことを基本とする
    →ELSE句は必須ではないですが、常に書くことをおすすめします。書かない場合は暗黙的にELSE NULLの扱いとなります。バグの温床となるので、ELSE句は書くべきです。

CASE式の使い方例

階級分けをする

参考書の例題でよく見る一番基礎的な使い方です。scoreが90点台、80点台、70点台、60点台、それ以外で表示するラベル(秀〜不可)を変更しています。

SELECT
    CASE
        WHEN score >= 90 THEN '秀'
        WHEN score >= 80 THEN '優'
        WHEN score >= 70 THEN '良'
        WHEN score >= 60 THEN '可'
        ELSE '不可'
    END
FROM test;

既存のデータを新しい体系で集計する

階級分けの応用例です。変換後のラベル毎の平均値を求めています。
CASE式全体に別名(AS materials)をつけていることがポイントです。この別名のお陰でGROUP BY句がmaterialsのみの記述ですみます。

もし、別名がない場合は、CASE式を丸ごとGROUP BY句に記載する必要があります。

SELECT CASE 
		WHEN 'チャーハン' THEN '米'
		WHEN 'ラーメン' THEN '小麦'
		WHEN 'カルボナーラ' THEN '小麦'
		WHEN 'ビビンバ' THEN '米'
		WHEN 'お好み焼き' THEN '小麦'
		WHEN 'じゃがバター' THEN '芋'
		WHEN 'フライドポテト' THEN '芋'
		ELSE 'その他' END AS materials,
		AVG(calory)
FROM food
GROUP BY materials;

区分ごとの集計を行う

国毎、性別毎の人口を計算しています。

このSQLはWHERE句で代用できますが、2つのSQLを発行する必要があります。
また、条件が増えた場合でもCASE式では、一つのSQLで実行することができます。

(CASE式で条件分岐)

SELECT 
	country_name,
	SUM(CASE WHEN sex = '1' THEN population ELSE 0 END) as man_cnt,
	SUM(CASE WHEN sex = '2' THEN population ELSE 0 END) as woman_cnt
FROM country
GROUP BY country_name;

(WHERE句で条件分岐)

SELECT country_name,count(population) FROM country WHERE sex = '1' BROUP BY country_name;
SELECT country_name,count(population) FROM country WHERE sex = '2' country_name;

UPDATE文で条件を分岐したい場合

数値型の列に対して、現在の値を判定対象として、別の値に変えたいケースを想定しています。
UPDATE文で複数の条件に分岐する必要がある場合、CASE式が便利です。

現在の給与が40万円以上の場合は10%DOWN、現在の給与が40万円以下の場合は10%UPする処理をCASE式で行っています。

UPDATE users SET salary = 
		CASE
			WHEN salary >= 400000 THEN salary * 0.9
			WHEN salary < 400000 THEN salary * 1.1
			ELSE salary 
		END
;

テーブル間の比較、マッチング(INやEXISTSとの組み合わせ)

CASE式は式の中で、BEETWEEN、LIKE、IN、EXISTSなどの述語群を使用することができます。特にINやEXISTSはサブクエリを引数に取れることから、異なるテーブル間で比較をする際にも活用することができます。

(INを使用)

SELECT 
	name,
	CASE WHEN user_id IN
	(SELECT user_id FROM test_result WHERE score =< 60) THEN '不合格'
	ELSE '合格' END AS '合否'
FROM users
;

(EXISTSを使用)

SELECT 
	name,
	CASE WHEN EXISTS
		(SELECT user_id FROM test_result tr WHERE score =< 60 
		AND u.user_id = tr.user_id) 
	THEN '不合格'
	ELSE '合格' END '合否'
FROM users u
;

終わりに

本記事はここまでとなります。ご覧いただきありがとうございました。

ご指摘等がございましたら頂けますと嬉しいです。
引き続き、プログラミングについて定期的に発信していきますのでよろしくお願いします!
また、もしよろしければtwitterもフォローしていただけると嬉しいです。

コメント