「条件によって表示する値を変えたい」「ステータスコードを分かりやすいテキストに変換したい」「NULL値を別の値に置き換えたい」…。
プログラミング言語には、条件によって値を切り替える3項演算子という便利な機能がありますよね。
実は、SQLにも同じような機能があるんです。それがCASE式です。
厳密には「3項演算子」という用語はSQLには存在しませんが、他のプログラミング言語の3項演算子と同じように、条件に応じて異なる値を返すことができます。CASE式を使えば、複雑な条件分岐も柔軟に表現できるんです。
この記事では、SQLで条件分岐を行う方法を、初心者の方にも分かりやすく解説していきます。
3項演算子とは?基本を理解しよう

まずは、3項演算子の概念から確認していきましょう。
他のプログラミング言語の3項演算子
多くのプログラミング言語には、3項演算子(三項演算子)があります。
JavaScript の例
// 条件 ? 真の場合の値 : 偽の場合の値
const result = age >= 18 ? "成人" : "未成年";
PHP の例
$message = $score >= 60 ? "合格" : "不合格";
Python の例
result = "合格" if score >= 60 else "不合格"
3項演算子の特徴
3項演算子には、以下の特徴があります。
| 特徴 | 説明 |
|---|---|
| 簡潔 | if-else文をコンパクトに書ける |
| 式として評価 | 値を返すので、変数への代入や関数の引数に使える |
| 可読性 | シンプルな条件なら読みやすい |
SQLにおける同等機能
SQLには「3項演算子」という構文はありませんが、同等の機能を持つものがいくつかあります。
- CASE式:最も汎用的で強力
- IF関数(MySQL):シンプルな条件分岐
- IIF関数(SQL Server、Access):2値の選択
- COALESCE関数:NULL値の処理
- NULLIF関数:特定値をNULLに変換
CASE式の基本
SQLで条件分岐を行う最も標準的な方法が、CASE式です。
CASE式とは
CASE式は、条件に応じて異なる値を返すSQL標準の構文です。
すべての主要なデータベース管理システムでサポートされています。
基本構文(単純CASE式)
値が特定の値と一致するかを判定します。
CASE 評価する列
WHEN 値1 THEN 結果1
WHEN 値2 THEN 結果2
WHEN 値3 THEN 結果3
ELSE デフォルト結果
END
使用例
SELECT
name,
CASE status
WHEN 0 THEN '未処理'
WHEN 1 THEN '処理中'
WHEN 2 THEN '完了'
ELSE '不明'
END AS status_text
FROM orders;
基本構文(検索CASE式)
より複雑な条件を指定できます。
CASE
WHEN 条件1 THEN 結果1
WHEN 条件2 THEN 結果2
WHEN 条件3 THEN 結果3
ELSE デフォルト結果
END
使用例
SELECT
name,
score,
CASE
WHEN score >= 90 THEN 'A'
WHEN score >= 80 THEN 'B'
WHEN score >= 70 THEN 'C'
WHEN score >= 60 THEN 'D'
ELSE 'F'
END AS grade
FROM students;
単純CASE式と検索CASE式の違い
| 種類 | 特徴 | 使いどころ |
|---|---|---|
| 単純CASE式 | 1つの列の値で分岐 | ステータスコードの変換など |
| 検索CASE式 | 複雑な条件式で分岐 | 範囲判定、複数列の条件など |
検索CASE式の方が柔軟性が高く、よく使われます。
実践的な使用例
CASE式の具体的な活用方法を見ていきましょう。
例1:ステータス表示の変換
数値コードを分かりやすいテキストに変換します。
SELECT
order_id,
customer_name,
CASE order_status
WHEN 0 THEN '注文受付'
WHEN 1 THEN '準備中'
WHEN 2 THEN '発送済み'
WHEN 3 THEN '配達完了'
WHEN 9 THEN 'キャンセル'
ELSE '状態不明'
END AS status_display
FROM orders;
例2:年齢層の分類
年齢を基に、年齢層を分類します。
SELECT
name,
age,
CASE
WHEN age < 20 THEN '10代'
WHEN age < 30 THEN '20代'
WHEN age < 40 THEN '30代'
WHEN age < 50 THEN '40代'
WHEN age < 60 THEN '50代'
ELSE '60代以上'
END AS age_group
FROM customers;
例3:価格帯の表示
商品価格を基に、価格帯を表示します。
SELECT
product_name,
price,
CASE
WHEN price < 1000 THEN '低価格帯'
WHEN price < 5000 THEN '中価格帯'
WHEN price < 10000 THEN '高価格帯'
ELSE 'プレミアム'
END AS price_range
FROM products;
例4:複数条件の組み合わせ
複数の列を使った条件分岐です。
SELECT
name,
score,
attendance_rate,
CASE
WHEN score >= 80 AND attendance_rate >= 90 THEN '優秀'
WHEN score >= 60 AND attendance_rate >= 80 THEN '良好'
WHEN score >= 60 THEN '合格'
ELSE '不合格'
END AS evaluation
FROM students;
例5:NULL値の処理
NULL値を特定の値に置き換えます。
SELECT
product_name,
CASE
WHEN stock_quantity IS NULL THEN '在庫情報なし'
WHEN stock_quantity = 0 THEN '在庫切れ'
WHEN stock_quantity < 10 THEN '残りわずか'
ELSE '在庫あり'
END AS stock_status
FROM products;
SELECT句での使用

CASE式は、SELECT句で最もよく使われます。
カラムの値を変換
SELECT
employee_id,
name,
CASE gender
WHEN 'M' THEN '男性'
WHEN 'F' THEN '女性'
ELSE '不明'
END AS gender_display
FROM employees;
計算結果に基づく分類
SELECT
product_name,
price,
cost,
price - cost AS profit,
CASE
WHEN (price - cost) > 1000 THEN '高収益'
WHEN (price - cost) > 0 THEN '通常'
ELSE '赤字'
END AS profit_status
FROM products;
複数のCASE式を併用
SELECT
name,
CASE
WHEN age < 20 THEN '若年層'
WHEN age < 60 THEN '中年層'
ELSE '高齢層'
END AS age_category,
CASE
WHEN income < 3000000 THEN '低所得'
WHEN income < 6000000 THEN '中所得'
ELSE '高所得'
END AS income_category
FROM customers;
WHERE句での使用
CASE式は、WHERE句でも使えます。
条件付きフィルタリング
-- 曜日によって異なる条件で検索
SELECT *
FROM sales
WHERE CASE DAYOFWEEK(sale_date)
WHEN 1 THEN amount >= 10000 -- 日曜日
WHEN 7 THEN amount >= 10000 -- 土曜日
ELSE amount >= 5000 -- 平日
END;
動的な条件
-- 商品カテゴリによって異なる在庫基準
SELECT *
FROM products
WHERE stock_quantity <
CASE category
WHEN 'A' THEN 100 -- カテゴリAは100未満
WHEN 'B' THEN 50 -- カテゴリBは50未満
ELSE 20 -- その他は20未満
END;
ORDER BY句での使用
並び順をカスタマイズできます。
優先度に基づいた並び替え
SELECT *
FROM tasks
ORDER BY
CASE priority
WHEN 'urgent' THEN 1
WHEN 'high' THEN 2
WHEN 'medium' THEN 3
WHEN 'low' THEN 4
ELSE 5
END,
due_date;
条件付きソート
-- 在庫状況で並び順を変える
SELECT *
FROM products
ORDER BY
CASE
WHEN stock_quantity = 0 THEN 1 -- 在庫切れを最初に
WHEN stock_quantity < 10 THEN 2 -- 在庫少を次に
ELSE 3 -- その他を最後に
END,
product_name;
UPDATE文での使用
既存データを条件に応じて更新できます。
条件付き値の更新
-- 価格を在庫状況に応じて調整
UPDATE products
SET price = CASE
WHEN stock_quantity = 0 THEN price * 1.2 -- 在庫切れは20%値上げ
WHEN stock_quantity < 10 THEN price * 1.1 -- 在庫少は10%値上げ
WHEN stock_quantity > 100 THEN price * 0.9 -- 過剰在庫は10%値下げ
ELSE price
END;
複数列の一括更新
-- 評価に基づいて給与とボーナスを調整
UPDATE employees
SET
salary = CASE
WHEN evaluation = 'A' THEN salary * 1.1
WHEN evaluation = 'B' THEN salary * 1.05
ELSE salary
END,
bonus = CASE
WHEN evaluation = 'A' THEN 500000
WHEN evaluation = 'B' THEN 300000
WHEN evaluation = 'C' THEN 100000
ELSE 0
END
WHERE department = 'Sales';
データベース別の条件分岐関数
CASE式以外にも、データベースごとに便利な関数があります。
MySQL の IF 関数
シンプルな2値選択に便利です。
-- IF(条件, 真の場合, 偽の場合)
SELECT
name,
IF(score >= 60, '合格', '不合格') AS result
FROM students;
CASE式と比較
-- CASE式での同等表現
SELECT
name,
CASE WHEN score >= 60 THEN '合格' ELSE '不合格' END AS result
FROM students;
IF関数の方が簡潔ですが、3つ以上の分岐にはCASE式が必要です。
SQL Server の IIF 関数
SQL Server 2012以降で使えます。
-- IIF(条件, 真の場合, 偽の場合)
SELECT
name,
IIF(age >= 18, '成人', '未成年') AS age_category
FROM users;
COALESCE 関数
NULL値を処理するための関数です。全データベースで使用できます。
-- 最初の非NULL値を返す
SELECT
name,
COALESCE(nickname, real_name, '名前なし') AS display_name
FROM users;
CASE式での同等表現
SELECT
name,
CASE
WHEN nickname IS NOT NULL THEN nickname
WHEN real_name IS NOT NULL THEN real_name
ELSE '名前なし'
END AS display_name
FROM users;
NULLIF 関数
2つの値が等しい場合にNULLを返します。
-- NULLIF(値1, 値2)
SELECT
name,
NULLIF(phone, '') AS phone -- 空文字をNULLに変換
FROM customers;
使用例:ゼロ除算の回避
SELECT
total_sales / NULLIF(order_count, 0) AS average_sale
FROM sales_summary;
-- order_countが0の場合、NULLになるのでエラーを回避
ネストしたCASE式
CASE式の中にさらにCASE式を入れることができます。
基本的なネスト
SELECT
name,
CASE gender
WHEN 'M' THEN
CASE
WHEN age < 20 THEN '男性・未成年'
ELSE '男性・成人'
END
WHEN 'F' THEN
CASE
WHEN age < 20 THEN '女性・未成年'
ELSE '女性・成人'
END
ELSE '不明'
END AS category
FROM users;
複雑な分類
SELECT
product_name,
CASE category
WHEN 'Electronics' THEN
CASE
WHEN price > 100000 THEN 'Premium Electronics'
WHEN price > 50000 THEN 'Standard Electronics'
ELSE 'Budget Electronics'
END
WHEN 'Clothing' THEN
CASE
WHEN price > 20000 THEN 'Luxury Clothing'
WHEN price > 10000 THEN 'Standard Clothing'
ELSE 'Budget Clothing'
END
ELSE 'Other Products'
END AS product_classification
FROM products;
注意点
ネストが深くなると、可読性が低下します。
可能なら、AND/OR条件で表現できないか検討しましょう。
-- ネストの代わりにAND条件を使う(推奨)
SELECT
name,
CASE
WHEN gender = 'M' AND age < 20 THEN '男性・未成年'
WHEN gender = 'M' AND age >= 20 THEN '男性・成人'
WHEN gender = 'F' AND age < 20 THEN '女性・未成年'
WHEN gender = 'F' AND age >= 20 THEN '女性・成人'
ELSE '不明'
END AS category
FROM users;
パフォーマンスへの影響

CASE式の使い方によっては、パフォーマンスに影響することがあります。
インデックスが効かないケース
WHERE句でCASE式を使うと、インデックスが効かないことがあります。
遅い例
-- カラムを加工しているため、インデックスが使えない
SELECT *
FROM products
WHERE CASE category
WHEN 'A' THEN price > 1000
WHEN 'B' THEN price > 2000
ELSE FALSE
END;
改善例
-- 条件を分解してインデックスを活用
SELECT *
FROM products
WHERE (category = 'A' AND price > 1000)
OR (category = 'B' AND price > 2000);
評価の順序
CASE式は、条件を上から順番に評価します。
最も頻繁にマッチする条件を先に書くと、効率的です。
-- 頻度の高い条件を先に
SELECT
CASE status
WHEN 1 THEN '処理中' -- 最も多い
WHEN 2 THEN '完了' -- 2番目に多い
WHEN 0 THEN '未処理' -- 少ない
WHEN 9 THEN 'キャンセル' -- 最も少ない
ELSE '不明'
END AS status_text
FROM orders;
複雑な計算の重複を避ける
同じ計算を複数回行わないようにしましょう。
非効率な例
SELECT
CASE
WHEN (price * 1.1 - cost) > 1000 THEN '高収益'
WHEN (price * 1.1 - cost) > 0 THEN '通常'
ELSE '赤字'
END
FROM products;
-- (price * 1.1 - cost) が複数回計算される
改善例
SELECT
CASE
WHEN profit > 1000 THEN '高収益'
WHEN profit > 0 THEN '通常'
ELSE '赤字'
END
FROM (
SELECT price * 1.1 - cost AS profit
FROM products
) AS subquery;
-- 計算は1回だけ
ベストプラクティス
CASE式を効果的に使うためのポイントです。
ELSE句を必ず含める
ELSE句がないと、条件に合わない場合にNULLが返されます。
-- 良い例:ELSE句がある
CASE status
WHEN 0 THEN '未処理'
WHEN 1 THEN '処理中'
WHEN 2 THEN '完了'
ELSE '不明' -- 予期しない値への対応
END
-- 悪い例:ELSE句がない
CASE status
WHEN 0 THEN '未処理'
WHEN 1 THEN '処理中'
WHEN 2 THEN '完了'
-- 他の値の場合はNULL
END
可読性を重視する
複雑なCASE式は、適切にインデントして読みやすくしましょう。
SELECT
name,
CASE
WHEN score >= 90 THEN 'A'
WHEN score >= 80 THEN 'B'
WHEN score >= 70 THEN 'C'
WHEN score >= 60 THEN 'D'
ELSE 'F'
END AS grade
FROM students;
データ型の一致
すべてのTHEN句とELSE句は、同じデータ型を返すようにしましょう。
-- 良い例:すべて文字列
CASE
WHEN score >= 60 THEN '合格'
ELSE '不合格'
END
-- 悪い例:データ型が混在
CASE
WHEN score >= 60 THEN '合格'
ELSE 0 -- 数値(型変換が必要になる)
END
複雑すぎる場合は別の方法を検討
CASE式が複雑になりすぎたら、以下を検討しましょう。
- ビューを作成して段階的に処理
- マスターテーブルを使ってJOIN
- アプリケーション側で処理
よくある間違いと対処法
CASE式を使う際の注意点です。
間違い1:WHENとTHENの混同
-- 間違い
CASE
WHEN score >= 60 WHEN '合格' -- WHENが2つ
ELSE '不合格'
END
-- 正しい
CASE
WHEN score >= 60 THEN '合格'
ELSE '不合格'
END
間違い2:ENDの忘れ
-- 間違い
SELECT
CASE status
WHEN 0 THEN '未処理'
WHEN 1 THEN '処理中'
ELSE '完了'
-- ENDがない
FROM orders;
-- 正しい
SELECT
CASE status
WHEN 0 THEN '未処理'
WHEN 1 THEN '処理中'
ELSE '完了'
END AS status_text
FROM orders;
間違い3:カンマの位置
-- 間違い
SELECT
name
CASE status -- カンマがない
WHEN 0 THEN '未処理'
END
FROM orders;
-- 正しい
SELECT
name, -- カンマが必要
CASE status
WHEN 0 THEN '未処理'
END AS status_text
FROM orders;
まとめ
SQLの条件分岐について解説してきました。
重要なポイント
- SQLには厳密な「3項演算子」はないが、CASE式で同等の機能を実現できる
- CASE式には単純CASE式と検索CASE式の2種類がある
- SELECT、WHERE、ORDER BY、UPDATE文など様々な場所で使える
- MySQLのIF関数、SQL ServerのIIF関数など、データベース固有の関数もある
- COALESCE関数でNULL値を処理できる
- ELSE句は必ず含めるべき
- ネストは可読性を考慮して使う
- パフォーマンスに影響することがあるので注意が必要
CASE式を使いこなせば、SQLでの条件分岐が柔軟に表現できるようになります。
まずは単純な条件から始めて、徐々に複雑な条件分岐にも挑戦してみてください。
データベースでの柔軟なデータ処理を実現していきましょう!

コメント