【SQL】CASE式で条件分岐を表現
達人に学ぶSQL徹底指南所の学習記録です。
やってること
ラベルの読み替えを行なっているだけ。
要点
- CASEは「式」だから、列名や定数をかける場所には常にかける
- 集約関数の中で使うことで、行持ちから列持ちへの水平展開が可能
- 逆に、集約関数を条件式に組み込むと
HAVING
を使わずにクエリをまとめられる - CASEを使うと複数のSQL分を1つにまとめられて、可読性もパフォーマンスも上がる
注意
END
の書き忘れに注意!ELSE
は必ず書こう!- エラーにはならないけど結果が違うというバグの温床になるため、たとえNULLでも明示的に書く癖をつけよう
問題1
mysql> select * from Greatests; +-----+---+---+---+ | id | x | y | z | +-----+---+---+---+ | A | 1 | 2 | 3 | | B | 5 | 5 | 2 | | C | 4 | 7 | 1 | | D | 3 | 3 | 8 | +-----+---+---+---+
xとyの最大値を取得する。
mysql> SELECT id, -> CASE WHEN x < y THEN y ELSE x END AS greates -> FROM Greatests; +----+---------+ | id | greates | +----+---------+ | A | 2 | | B | 5 | | C | 7 | | D | 3 | +----+---------+
xyzの最大値を取得する。
mysql> SELECT id, -> CASE WHEN CASE WHEN x < y THEN y ELSE x END < z THEN z -> ELSE CASE WHEN x < y THEN y ELSE x END END AS greatest -> FROM Greatests; +----+----------+ | id | greatest | +----+----------+ | A | 3 | | B | 5 | | C | 7 | | D | 8 | +----+----------+
問題2
mysql> SELECT * FROM pref_samples; +-----------+-----+------------+ | pref_name | sex | population | +-----------+-----+------------+ | 徳島 | 1 | 60 | | 徳島 | 2 | 40 | | 香川 | 1 | 100 | | 香川 | 2 | 100 | | 愛媛 | 1 | 100 | | 愛媛 | 2 | 50 | | 高知 | 1 | 100 | | 高知 | 2 | 100 | | 福岡 | 1 | 100 | | 福岡 | 2 | 200 | | 佐賀 | 1 | 20 | | 佐賀 | 2 | 80 | | 長崎 | 1 | 125 | | 長崎 | 2 | 125 | | 東京 | 1 | 250 | | 東京 | 2 | 150 | +-----------+-----+------------+
性別ごとに、全国、各県、四国の人口を取得
mysql> SELECT sex, -> SUM(population) AS total, -> SUM(CASE WHEN pref_name = '徳島' THEN population ELSE 0 END) AS 徳島, -> SUM(CASE WHEN pref_name = '香川' THEN population ELSE 0 END) AS 香川, -> SUM(CASE WHEN pref_name = '愛媛' THEN population ELSE 0 END) AS 愛媛, -> SUM(CASE WHEN pref_name = '高知' THEN population ELSE 0 END) AS 高知, -> SUM(CASE WHEN pref_name IN ('徳島', '香川', '愛媛', '高知') THEN population ELSE 0 END) AS 四国 -> FROM pref_samples -> GROUP BY sex; +-----+-------+--------+--------+--------+--------+--------+ | sex | total | 徳島 | 香川 | 愛媛 | 高知 | 四国 | +-----+-------+--------+--------+--------+--------+--------+ | 1 | 855 | 60 | 100 | 100 | 100 | 360 | | 2 | 845 | 40 | 100 | 50 | 100 | 290 | +-----+-------+--------+--------+--------+--------+--------+