MySQLのCASE句とは?Javaのswitch文と比較して新人エンジニア向けにやさしく解説

こんにちは。ゆうせいです。

今回は、MySQLのCASE句について、Javaのswitch文と比較しながら新人エンジニア向けに解説します。

CASE句は、SQLの中で条件分岐を行うための書き方です。

Javaで条件分岐といえば、if文やswitch文を思い浮かべる人が多いと思います。

MySQLのCASEも、考え方としてはそれに近いです。

ただし、MySQLのCASEは「処理の流れを変える」というより、「条件に応じて返す値を変える」ために使うことが多いです。

たとえるなら、Javaのswitch文は「行き先を分ける案内係」です。

一方で、MySQLのCASE句は「条件に応じて表示ラベルを貼り替える係」です。

同じ分岐でも、使う場所と目的が少し違います。

MySQLのCASE句とは何か

MySQLのCASE句とは、SQLの中で「もし条件Aなら値A、条件Bなら値B、それ以外なら値C」のように、条件によって返す値を変えるための仕組みです。

MySQL公式ドキュメントでは、CASE演算子には2つの構文があり、条件が真になった最初の結果を返し、どれにも当てはまらない場合はELSEの結果、ELSEがなければNULLを返すと説明されています。なお、ストアドプログラム内で使うCASE文とは構文が少し異なります。

まずは、基本形を見てみましょう。

SELECT
    car_id,
    name,
    price,
    CASE
        WHEN price >= 3000000 THEN '高価格'
        WHEN price >= 1500000 THEN '中価格'
        ELSE '低価格'
    END AS price_rank
FROM cars;




このSQLは、車の価格に応じて、price_rankという表示用の分類を作っています。

priceの値CASEの結果
3000000以上高価格
1500000以上3000000未満中価格
1500000未満低価格

ポイントは、carsテーブルにprice_rankというカラムがなくても、SELECT結果の中で一時的に分類を作れることです。

学校の成績でたとえるなら、点数カラムだけがある状態から、CASEを使って「A評価」「B評価」「C評価」というラベルを付けるようなものです。

CASE句の2つの書き方

MySQLのCASEには、大きく2つの書き方があります。

種類特徴Javaで近いもの
単純CASE1つの値を複数の候補と比較するswitch文に近い
検索CASEWHENごとに自由な条件を書くif、else ifに近い

新人エンジニアは、まずこの2つを分けて覚えると理解しやすいです。

単純CASE:Javaのswitch文に近い書き方

単純CASEは、1つの値を見て、どの値に一致するかで結果を変える書き方です。

SELECT
    car_id,
    name,
    status,
    CASE status
        WHEN 1 THEN '販売中'
        WHEN 2 THEN '売約済み'
        WHEN 3 THEN '販売停止'
        ELSE '不明'
    END AS status_name
FROM cars;




このCASEでは、statusの値を見ています。

statusstatus_name
1販売中
2売約済み
3販売停止
それ以外不明

Javaのswitch文で書くと、考え方は次のようになります。

String statusName;

switch (status) {
    case 1:
        statusName = "販売中";
        break;
    case 2:
        statusName = "売約済み";
        break;
    case 3:
        statusName = "販売停止";
        break;
    default:
        statusName = "不明";
        break;
}




かなり似ていますよね。

どちらも「statusの値が1なら販売中、2なら売約済み、3なら販売停止」という分岐をしています。

ただし、MySQLのCASEはSQLの中で値を返すために使っています。

Javaのswitch文は、Javaプログラムの中で処理を分岐させるために使っています。

検索CASE:Javaのif、else ifに近い書き方

検索CASEは、WHENごとに条件式を書けるCASEです。

価格帯のように、「300万円以上」「150万円以上」のような範囲判定をしたい場合に使いやすいです。

SELECT
    car_id,
    name,
    price,
    CASE
        WHEN price >= 3000000 THEN '高価格'
        WHEN price >= 1500000 THEN '中価格'
        ELSE '低価格'
    END AS price_rank
FROM cars;




Javaのif文で書くと、次のようなイメージです。

String priceRank;

if (price >= 3000000) {
    priceRank = "高価格";
} else if (price >= 1500000) {
    priceRank = "中価格";
} else {
    priceRank = "低価格";
}




検索CASEは、Javaのswitch文よりもif、else ifに近いです。

なぜなら、WHENの中に自由な条件を書けるからです。

書き方向いている条件
単純CASEstatus = 1、status = 2 のような一致判定
検索CASEprice >= 3000000 のような範囲判定

迷ったら、まず検索CASEを使うと柔軟に書けます。

Javaのswitch文との大きな違い

MySQLのCASE句とJavaのswitch文は似ていますが、かなり重要な違いがあります。

比較MySQLのCASE句Javaのswitch文
使う場所SQLの中Javaプログラムの中
主な目的条件に応じて値を返す条件に応じて処理を分岐する
返すもの処理の流れ、またはswitch式なら値
よく使う場面SELECT、ORDER BY、集計業務ロジック、画面制御、処理分岐
終了の書き方ENDbreakやreturnなど
デフォルトELSEdefault

特に大事なのは、「MySQLのCASEは値を返す」という点です。

Javaのswitch文は、何かの処理を実行するために使うことが多いです。

一方で、MySQLのCASEは、SELECT結果の1列として値を作るために使うことが多いです。

CASE句はSELECTの中でよく使う

CASE句の一番よくある使い方は、SELECT句の中で表示用の値を作る方法です。

たとえば、carsテーブルに次のようなデータがあるとします。

car_idnamepricedeleted_at
1プリウス2500000NULL
2高級SUV4500000NULL
3軽自動車1200000NULL
4旧モデル8000002026-01-01 10:00:00

このデータに対して、価格ランクを表示したい場合です。

SELECT
    car_id,
    name,
    price,
    CASE
        WHEN price >= 3000000 THEN '高価格'
        WHEN price >= 1500000 THEN '中価格'
        ELSE '低価格'
    END AS price_rank
FROM cars;




結果は次のようなイメージになります。

car_idnamepriceprice_rank
1プリウス2500000中価格
2高級SUV4500000高価格
3軽自動車1200000低価格
4旧モデル800000低価格

price_rankは、テーブルに保存されているカラムではありません。

SELECTするときにCASEで作った一時的な表示用の値です。

レストランでたとえるなら、料理そのものは同じでも、メニュー表で「おすすめ」「激辛」「低カロリー」のラベルを付けるようなものです。

CASE句で論理削除の状態を表示する

deleted_atを使った論理削除でも、CASE句はよく使えます。

論理削除とは、DELETEで物理的に消すのではなく、deleted_atに日時を入れて削除済み扱いにする方法です。

deleted_atがNULLなら有効データ、NULLでなければ削除済みデータと考えます。

SELECT
    car_id,
    name,
    price,
    deleted_at,
    CASE
        WHEN deleted_at IS NULL THEN '有効'
        ELSE '削除済み'
    END AS delete_status
FROM cars;




このSQLでは、deleted_atの状態に応じて、有効または削除済みを表示しています。

deleted_atdelete_status
NULL有効
日時あり削除済み

Javaで書くなら、次のようなif文のイメージです。

String deleteStatus;

if (deletedAt == null) {
    deleteStatus = "有効";
} else {
    deleteStatus = "削除済み";
}




ここはJavaのswitch文よりif文に近いですね。

NULL判定や範囲判定では、検索CASEが便利です。

CASE句はORDER BYでも使える

CASE句は、SELECT句だけでなくORDER BYでも使えます。

ORDER BYは、検索結果を並び替えるための句です。

たとえば、車を「販売中を先に、販売停止を後に」並べたい場合があります。

SELECT
    car_id,
    name,
    status
FROM cars
ORDER BY
    CASE status
        WHEN 1 THEN 1
        WHEN 2 THEN 2
        WHEN 3 THEN 3
        ELSE 9
    END;




このSQLでは、statusの値を並び替え用の数字に変換しています。

status並び替え用の値意味
11販売中
22売約済み
33販売停止
その他9最後に回す

Javaでソート条件を作るのに近い考え方です。

ただし、SQL側で並び順を作っているので、DBから取得した時点で並び替え済みになります。

画面側やJava側で並び替えるより、SQLで済むならSQLで行うほうがシンプルな場面もあります。

CASE句は集計でも使える

CASE句は、集計と組み合わせるとかなり便利です。

たとえば、carsテーブルの中で、高価格、中価格、低価格の件数を数えたいとします。

SELECT
    CASE
        WHEN price >= 3000000 THEN '高価格'
        WHEN price >= 1500000 THEN '中価格'
        ELSE '低価格'
    END AS price_rank,
    COUNT(*) AS car_count
FROM cars
WHERE deleted_at IS NULL
GROUP BY
    CASE
        WHEN price >= 3000000 THEN '高価格'
        WHEN price >= 1500000 THEN '中価格'
        ELSE '低価格'
    END;




結果は次のようなイメージです。

price_rankcar_count
高価格5
中価格12
低価格8

このように、CASEを使うと、テーブルにprice_rankというカラムがなくても、価格帯ごとの集計ができます。

これはとても実務的です。

売上分析、在庫分析、ユーザー分類、ログ分析などでよく使われます。

SUMとCASEを組み合わせる

さらに、SUMとCASEを組み合わせると、条件に合う件数を横並びで集計できます。

SELECT
    SUM(CASE WHEN price >= 3000000 THEN 1 ELSE 0 END) AS high_price_count,
    SUM(CASE WHEN price >= 1500000 AND price < 3000000 THEN 1 ELSE 0 END) AS middle_price_count,
    SUM(CASE WHEN price < 1500000 THEN 1 ELSE 0 END) AS low_price_count
FROM cars
WHERE deleted_at IS NULL;




このSQLは、価格帯ごとの件数を1行で返します。

high_price_countmiddle_price_countlow_price_count
5128

CASEの中で、条件に合う場合は1、合わない場合は0を返しています。

その1と0をSUMで合計することで、条件に合う件数を数えています。

記号の式で表すと、次のようなイメージです。

count = sum(1 if condition else 0)

日本語に置き換えると、次の意味です。

件数 = 合計(条件に合えば1、それ以外なら0)

これは、出席を数えるイメージに近いです。

出席している人を1、欠席している人を0として合計すると、出席人数が出ますよね。

CASEとSUMの組み合わせも同じです。

CASE句の判定順序に注意する

CASE句では、WHENは上から順番に判定されます。

最初に条件を満たしたTHENが採用されます。

MySQL公式ドキュメントでも、CASE演算子は最初に真になった条件の結果を返すと説明されています。

ここはとても重要です。

悪い例を見てみましょう。

SELECT
    name,
    price,
    CASE
        WHEN price >= 1500000 THEN '中価格'
        WHEN price >= 3000000 THEN '高価格'
        ELSE '低価格'
    END AS price_rank
FROM cars;




このSQLでは、priceが4000000でも、最初のprice >= 1500000に当てはまってしまいます。

そのため、高価格ではなく中価格になります。

正しくは、条件の厳しいほうを先に書きます。

SELECT
    name,
    price,
    CASE
        WHEN price >= 3000000 THEN '高価格'
        WHEN price >= 1500000 THEN '中価格'
        ELSE '低価格'
    END AS price_rank
FROM cars;




Javaのif、else ifでも同じです。

if (price >= 1500000) {
    priceRank = "中価格";
} else if (price >= 3000000) {
    priceRank = "高価格";
}




このJavaコードでも、300万円以上の価格は先に150万円以上の条件に引っかかります。

つまり、高価格判定まで到達しません。

CASE句では、条件の順番が結果を左右します。

範囲が重なる条件を書くときは、必ず上から順に確認してください!

ELSEを書かないとどうなるか

CASE句では、ELSEを省略できます。

ただし、どのWHENにも当てはまらなかった場合はNULLになります。

MySQL公式ドキュメントでも、CASE演算子は条件に一致せずELSEがない場合、NULLを返すと説明されています。

例を見てみましょう。

SELECT
    car_id,
    name,
    status,
    CASE status
        WHEN 1 THEN '販売中'
        WHEN 2 THEN '売約済み'
    END AS status_name
FROM cars;




このSQLでは、statusが3や9の場合、status_nameはNULLになります。

statusstatus_name
1販売中
2売約済み
3NULL
9NULL

NULLになっても問題ない場合は、ELSEなしでも構いません。

しかし、画面表示で使うならELSEを書いたほうが安全です。

CASE status
    WHEN 1 THEN '販売中'
    WHEN 2 THEN '売約済み'
    ELSE '不明'
END AS status_name




Javaのswitch文でも、defaultを書いておくと想定外の値に対応できますよね。

MySQLのCASEでも、ELSEはJavaのdefaultに近い役割です。

CASE句とCASE文の違い

少しややこしいのですが、MySQLにはCASE演算子とCASE文があります。

普段のSELECTでよく使うのは、CASE演算子です。

ストアドプロシージャなどの中で処理分岐に使うものは、CASE文です。

MySQL公式ドキュメントでも、ストアドプログラム用のCASE文はCASE演算子と異なり、ENDではなくEND CASEで終わると説明されています。

種類主な使用場所終了の書き方用途
CASE演算子SELECT、ORDER BY、GROUP BYなどEND条件に応じて値を返す
CASE文ストアドプロシージャ、ストアドファンクションEND CASE処理の流れを分岐する

新人エンジニアが最初に覚えるべきなのは、SELECTで使うCASE演算子です。

ストアドプロシージャを使う段階になったら、CASE文も学べばよいです。

Javaのswitch式との比較

最近のJavaでは、switchを式として使う書き方もあります。

switch式は、値を返せます。

String statusName = switch (status) {
    case 1 -> "販売中";
    case 2 -> "売約済み";
    case 3 -> "販売停止";
    default -> "不明";
};




この書き方は、従来のswitch文よりMySQLのCASE句に近いです。

比較MySQL CASEJava switch式
値を返すか返す返す
デフォルトELSEdefault
使う場所SQLJava
終了END};

ただし、実務では「DBで分類すべきか」「Javaで分類すべきか」を考える必要があります。

何でもCASEにする、何でもJavaのswitchにする、どちらも極端です。

CASE句を使うべき場面

CASE句を使うべき場面を整理します。

場面理由
一覧表示用のラベルを作るDB取得時に表示用の値を作れるstatusを販売中、売約済みに変換
集計用の分類を作る価格帯や年齢層ごとに集計できる高価格、中価格、低価格
並び順を制御する単純な昇順・降順ではない順番を作れる販売中を先、販売停止を後
NULLや状態値を見やすくする画面やレポートでわかりやすいdeleted_atで有効、削除済みを表示
条件付き集計をするSUMと組み合わせて件数を数えられる価格帯ごとの件数

SQLで集計や一覧を作るとき、CASE句は非常に便利です。

特に、管理画面やレポート画面でよく使います。

Javaのswitch文を使うべき場面

一方で、Javaのswitch文を使ったほうがよい場面もあります。

場面理由
業務ロジックを分岐するDBではなくアプリの処理だから支払い方法ごとに処理を変える
複雑な処理を実行するSQLで書くと読みにくくなるメール送信、ファイル出力、API呼び出し
状態ごとに別メソッドを呼ぶ処理の分岐が主目的だから注文状態ごとの処理
画面側の制御をする表示ロジックがアプリ側にあるからボタン表示、遷移先変更

MySQLのCASE句は、値を作るのが得意です。

Javaのswitch文は、処理を分けるのが得意です。

ここを分けて考えると、設計がきれいになります。

DBでCASEを書くか、Javaでswitchを書くか

実務では、「この分岐はSQLで書くべきか、Javaで書くべきか」で迷うことがあります。

判断の目安を表にします。

判断ポイントSQLのCASE向きJavaのswitch向き
目的取得結果の表示や集計業務処理の分岐
処理内容値を返すだけ複数の処理を実行する
変更頻度DB検索条件や帳票寄りアプリ仕様や画面仕様寄り
読みやすさSQL内に書くと自然SQLに書くと複雑すぎる
再利用複数画面で同じSQL集計を使うJava内の複数処理で使う

たとえば、statusの数値を表示名に変換するだけなら、CASE句でもよいです。

CASE status
    WHEN 1 THEN '販売中'
    WHEN 2 THEN '売約済み'
    ELSE '不明'
END AS status_name




しかし、statusによってメールを送ったり、在庫を更新したり、外部APIを呼んだりするなら、Java側でswitch文を使うべきです。

switch (status) {
    case 1:
        sendAvailableMail();
        break;
    case 2:
        updateContractInfo();
        break;
    default:
        logUnknownStatus();
        break;
}




SQLはデータを取り出す場所です。

Javaは業務処理を組み立てる場所です。

役割分担を意識してください。

CASE句でよくあるミス

ミス1:ENDを書き忘れる

CASE句は、必ずENDで閉じます。

悪い例です。

SELECT
    name,
    CASE
        WHEN price >= 3000000 THEN '高価格'
        ELSE '通常価格'
FROM cars;




ENDがないため、SQLエラーになります。

良い例です。

SELECT
    name,
    CASE
        WHEN price >= 3000000 THEN '高価格'
        ELSE '通常価格'
    END AS price_rank
FROM cars;




ミス2:ELSEを書かずにNULLになる

ELSEを書かないと、どの条件にも当てはまらない場合にNULLになります。

画面表示でNULLが出ると、ユーザーにとってわかりにくい場合があります。

CASE status
    WHEN 1 THEN '販売中'
    WHEN 2 THEN '売約済み'
END AS status_name

statusが3ならNULLです。




不明表示が必要なら、ELSEを書きましょう。

CASE status
    WHEN 1 THEN '販売中'
    WHEN 2 THEN '売約済み'
    ELSE '不明'
END AS status_name




ミス3:条件の順番を間違える

範囲条件では、順番がとても重要です。

悪い例です。

CASE
    WHEN price >= 1500000 THEN '中価格'
    WHEN price >= 3000000 THEN '高価格'
    ELSE '低価格'
END




良い例です。

CASE
    WHEN price >= 3000000 THEN '高価格'
    WHEN price >= 1500000 THEN '中価格'
    ELSE '低価格'
END




条件は上から順番に見られます。

厳しい条件、狭い条件を先に書くのが基本です。

ミス4:複雑な業務ロジックをCASEに詰め込みすぎる

CASE句は便利ですが、何でも詰め込むとSQLが読みにくくなります。

悪い方向に進むと、SELECT文の中に長いCASEが何個も並び、誰も読めないSQLになります。

CASE句は、表示用ラベル、簡単な分類、集計用の条件分岐に使うのが基本です。

複雑な処理はJava側に寄せましょう。

CASE句を使った実務的なSQL例

最後に、carsテーブルを使った実務寄りの例を見てみましょう。

SELECT
    car_id,
    name,
    price,
    CASE
        WHEN price >= 3000000 THEN '高価格'
        WHEN price >= 1500000 THEN '中価格'
        ELSE '低価格'
    END AS price_rank,
    CASE
        WHEN deleted_at IS NULL THEN '有効'
        ELSE '削除済み'
    END AS delete_status
FROM cars
ORDER BY
    CASE
        WHEN deleted_at IS NULL THEN 1
        ELSE 2
    END,
    price DESC;




このSQLでは、次のことをしています。

処理内容
price_rank価格に応じて高価格、中価格、低価格を表示
delete_statusdeleted_atを見て有効、削除済みを表示
ORDER BYのCASE有効データを先に、削除済みを後に並べる
price DESC価格が高い順に並べる

このように、CASE句は一覧画面や管理画面のSQLでとても役立ちます。

Java側で取得後に加工することもできますが、SQLで自然に書ける表示分類なら、CASE句を使うとシンプルになることがあります。

まとめ

MySQLのCASE句は、SQLの中で条件分岐を行い、条件に応じた値を返すための仕組みです。

Javaのswitch文と似ていますが、目的が違います。

ポイントMySQLのCASE句Javaのswitch文
主な役割条件に応じて値を返す条件に応じて処理を分ける
よく使う場所SELECT、ORDER BY、GROUP BY、集計Javaの業務ロジック
デフォルトELSEdefault
終了ENDbreak、return、またはswitch式の終端
向いていること表示用ラベル、分類、条件付き集計メール送信、API呼び出し、状態ごとの処理

一言でまとめるなら、MySQLのCASE句は「SQLの中で条件に応じた表示値や集計値を作るための分岐」です。

Javaのswitch文は「Javaプログラムの処理そのものを分岐させるための構文」です。

新人エンジニアは、まず次の3つを覚えてください。

覚えること理由
CASEは値を返すSELECT結果の1列として使いやすい
WHENは上から順番に判定される条件の順番を間違えると結果が変わる
ELSEを書いたほうが安全想定外の値でNULLになるのを防げる

今後の学習では、まずSELECT句でCASEを使って表示ラベルを作る練習をしてください。

次にORDER BYで並び順を制御し、最後にSUMやCOUNTと組み合わせた条件付き集計に進むとよいです。

Javaのswitch文と比較しながら、「SQLで値を作るのか」「Javaで処理を分けるのか」を考えられるようになると、DBとアプリの役割分担がかなり理解しやすくなります!

セイ・コンサルティング・グループでは新人エンジニア研修のアシスタント講師を募集しています。

投稿者プロフィール

山崎講師
山崎講師代表取締役
セイ・コンサルティング・グループ株式会社代表取締役。
岐阜県出身。
2000年創業、2004年会社設立。
IT企業向け人材育成研修歴業界歴20年以上。
すべての無駄を省いた費用対効果の高い「筋肉質」な研修を提供します!
この記事に間違い等ありましたらぜひお知らせください。

学生時代は趣味と実益を兼ねてリゾートバイトにいそしむ。長野県白馬村に始まり、志賀高原でのスキーインストラクター、沖縄石垣島、北海道トマム。高じてオーストラリアのゴールドコーストでツアーガイドなど。現在は野菜作りにはまっている。