GoQSystem Tech Blog

GoQSystemのテックブログ

DB側で条件分岐をしたい時【CASE式】

この記事は「GoQSystem Advent Calendar 2025」4日目の記事です。

こんにちは、GoQSystemでバックエンドエンジニアをしている品川です。

条件によって取得する値を変えたい時、これまではPHP側で条件分岐を書いていました。 今回、SQL側でも条件分岐ができること、場合によってはその方がパフォーマンスも良くなることを知りました。未来の自分に向けてまとめておきます。

CASE式の基本

SQLで条件分岐をしたい時にとても便利なのがCASE式です。 CASE式は以下2つの書き方ができます。

例1

CASE color
    WHEN 'white' THEN ''
    WHEN 'black' THEN ''
    ELSE NULL
END

例2

CASE
    WHEN color = 'white' THEN ''
    WHEN color = 'black' THEN ''
    ELSE NULL
END

例1、例2はそれぞれ単純CASE式、検索CASE式と呼ばれ、どちらを使っても良いのですが、単純CASE式は「指定したカラムの値が、特定の値と等しいか(=)」しか判定できないのに対して、検索CASE式は「あらゆる条件式(不等号、複数カラム、NULL判定など)」を書くことができるので、検索CASE式の方を使うのをおすすめします。

ELSE NULLは省略可能で、省略した場合は暗黙的にELSE NULLとして解釈されます。ただ、うっかり書き忘れた時に意図せずNULLを返してしまったり、他の人がコードを読んだときにNULLが返ってくることが一見してわかりづらいので、省略せずに常に書く習慣をつけた方が良いです。

また、CASE式の終わりにENDを書き忘れるのもよくあるミスですが、こちらは省略不可で書き忘れるとエラーになります。注意してください。

CASE式を使った具体例

実際にどのような使い方ができるか、いくつか具体例を紹介します。

年齢によって成人/未成年を判定する

customer_informationテーブル

id name age
1 佐藤 20
2 鈴木 16
3 田中 NULL
SELECT
    id,
    name,
    CASE
        WHEN age >= 18 THEN '成人'
        WHEN age < 18 THEN '未成年'
        ELSE '不明'
    END AS age
FROM customer_information;

実行結果

id name age
1 佐藤 成人
2 鈴木 未成年
3 田中 不明

都道府県から地域を判定する

addressテーブル

zip_code prefecture city street_address
5300001 大阪 大阪市 梅田1丁目
6000001 京都 京都市 四条通
7600001 香川 高松市 中央通り
7700001 徳島 徳島市 駅前通
1000001 東京 千代田区 千代田1丁目
SELECT
    zip_code,
    CASE
        WHEN prefecture IN ('大阪', '京都', '兵庫', '奈良') THEN '関西'
        WHEN prefecture IN ('香川', '徳島', '愛媛', '高松') THEN '四国'
        ELSE 'その他'
    END AS region,
    city,
    street_address
FROM address;

実行結果

zip_code region city street_address
5300001 関西 大阪市 梅田1丁目
6000001 関西 京都市 四条通
7600001 四国 高松市 中央通り
7700001 四国 徳島市 駅前通
1000001 その他 千代田区 千代田1丁目

動物の種類ごとに頭数をカウントする

CASE式は集約関数(SUMやCOUNTなど)の中で使うこともできます。 これを利用すると、行として持っているデータを列に変換して集計する、いわゆる「クロス集計」のようなことがSQLだけで可能になります。

animalsテーブル

id species
1
2
3
4
5
SELECT
    SUM(CASE WHEN species = '' THEN 1 ELSE 0 END) AS number_of_dogs,
    SUM(CASE WHEN species = '' THEN 1 ELSE 0 END) AS number_of_cats
FROM animals;

実行結果

number_of_dogs number_of_cats
3 2

まとめ

CASE式を使うことで、SQLの段階で柔軟な条件分岐を行えるようになり、アプリケーション側(GoQSystemではPHPを使用しています)での分岐処理を減らすことができます。

また、大量のレコードを扱う場合は、すべての値を取得してからアプリケーション側でループ処理を行うのに比べて、SQL側の条件分岐により値を整形してから取得する方が、データ転送量の削減や処理速度の向上につながることもあります。(ただし、必ずしも常にSQL側の方が速いわけではありません。条件やインデックス、DB負荷などにより最適解は変わるため、状況に応じて使い分けることが大切です。)

PHPSQL両方の知識を深めることによって、状況に応じた最適な手法を取ることができます。

参考文献

www.shoeisha.co.jp