データベースから取り出したデータに応じた場合分け
データベースからデータを取り出すとき、そのままの姿では使いにくいことがあります。
「性別が『1』って何だよ。男って書けよ」
「点数が『85』じゃなくて、合格か不合格かだけ教えてくれ」
データを取ってきてから、ExcelやPHPで加工していませんか。
それは二度手間になってしまいます。
SQLには、データを取得する瞬間に中身を別の値に書き換える魔法があります。
それが「CASE(ケース)」式です。
これは、SQLの中に埋め込める「if文(条件分岐)」です。
今日は、無機質なデータを人間に分かりやすい言葉に変身させる、この便利な構文を解説します。
基本構文:WHENとTHENのリズム
CASE式の書き方は独特ですが、リズムさえ覚えれば簡単です。
- CASE (これから場合分けするぞ)
- WHEN 条件 THEN 結果 (もしこうなら、こう変身しろ)
- ELSE 結果 (それ以外なら、これになれ)
- END (変身完了)
SELECT 名前,
CASE
WHEN 条件A THEN '条件AにあてはまったのでAだよ'
WHEN 条件B THEN '条件BにあてはまったのでBだよ'
ELSE 'その他'
END
FROM テーブル名;Code language: PHP (php)
SELECTの列を指定する場所に、この長い呪文をねじ込みます。
すると、条件に合った値に書き換わって出力されます。
これで「名前」は、以下の3つのどれに該当したかによって姿を変えます。
- 条件Aに該当したのか?
- 条件Bに該当したのか?
- 条件Aにも条件Bにも該当しなかったのか?
このブログでたびたび解説しているPHPで書くと、以下のようなイメージです。
// もしPHPで書くなら...
if (条件A) {
$name = '条件AにあてはまったのでAだよ';
} elseif (条件B) {
$name = '条件BにあてはまったのでBだよ';
} else {
$name = 'その他';
}Code language: PHP (php)
PHPのif文の分岐では{で開始して}で終了するのが通常ですが、SQLではCASEで初めてENDで終了するのです。
PHPのif文と同様で、上の条件にあてはまったらそこで終了となり、下のWHENは実行されないので注意です。
これは、ifにあてはまったらその直後のelseifが実行されないのと同じです。
前述の通り、if文とCASE式は似ているので、対応イメージを以下の表に示します。
| PHPのif文 | SQLのCASE式 |
| if (条件A) { | CASE WHEN 条件A |
| $res = ‘Aだよ’; | THEN ‘Aだよ’ |
| } elseif (条件B) { | WHEN 条件B |
| $res = ‘Bだよ’; | THEN ‘Bだよ’ |
| } else { | ELSE |
| $res = ‘その他’; | ‘その他’ |
| } | END |
具体例:男と女を人間に戻す
よくあるデータベース設計では、性別を数字で管理しています。
1が男性、2が女性、といった具合です。
これをそのまま画面に出すと、ユーザーは混乱します。
どんな設計かにもよりますが、CASE式を使って、取得時に日本語に変換する方が便利なこともあります。やってみましょう。
SELECT name,
CASE
WHEN gender = 1 THEN '男性'
WHEN gender = 2 THEN '女性'
ELSE '不明'
END AS gender_text
FROM users;Code language: PHP (php)
これで、結果は「1」ではなく「男性」と表示されます。
AS gender_text と書くことで、この新しい列に名前をつけています。
この名前をつけてわかりやすくする構文のことを、「別名」とか、「エイリアス」と言います。
PHPで例えると、$arr[‘gender_text’]のように、連想配列のキーを決めているようなイメージです。
上記のようにCASE式で「男性」や「女性」のように翻訳済の文言をセットした場合、プログラム側でif (gender == 1)…と書く必要はありません。
SQLが気を利かせて、最初から翻訳済みのデータを渡してくれるのです。
1や2といった値に対応する文言はPHPなどのサーバサイド言語側で決めたい!という場合はSQLでCASE式で翻訳することなく、そのままPHP側に1や2といった値を渡すと良いでしょう。
応用:点数でランク付けする
数字の範囲で条件分岐することも可能です。
テストの点数(score)に応じて、通知表のようなランクをつけてみましょう。
SELECT name, score,
CASE
WHEN score >= 90 THEN 'Sランク'
WHEN score >= 80 THEN 'Aランク'
WHEN score >= 60 THEN 'Bランク'
ELSE '追試確定'
END AS rank
FROM tests;Code language: PHP (php)
上から順番に判定されます。
95点の人は、最初の score >= 90 に引っかかるので「Sランク」になります。
50点の人は、どれにも引っかからないので ELSE の「追試確定」になります。
これで、冷酷な数字の羅列が、意味のある評価リストに早変わりします。
注意点:ENDを忘れると・・・!?
CASE式を書くとき、初心者が一人残らず必ずやるミスがあります。
最後のENDの書き忘れです。
-- エラーになる例
CASE
WHEN score >= 60 THEN '合格'
ELSE '不合格'
-- ここにENDがない!Code language: PHP (php)
END がないと、データベースはどこまでが条件分岐なのか分かりません。
「まだ続くのか? まだ条件があるのか?」と待ち続け、最終的に構文エラーを吐いて倒れます。
「SQLではCASEで初めてENDで終了」と前述しましたが、「CASEで始めたらENDで締める」。
これはセットです。
お箸は2本で1膳。CASEはENDとセットで1人前です。
まとめ:SQLでできることはSQLでやろう
- CASE WHEN THEN:条件に合わせて値を変身させる。
- ELSE:どれにも当てはまらない場合の受け皿。
- END:終わりの合図。忘れずに!
データを取得した後、PHPやExcelなどでチマチマ加工するのは、スーパーで買った魚を自宅で捌くようなものです。
場合によってそれが手段として適切か否か、見極めていきましょう。
CASE式を使えば、スーパー(データベース)の時点で「三枚おろし」にして渡してくれます。
料理(アプリ開発)の手間を減らすために、下処理はSQLに任せちゃいましょう。


コメント