【完全版】SQLのCASE文とは?基本から応用まで実例付きで解説

※本サイトにはプロモーション・広告が含まれています。

(最終更新月:2023年5月)

✔このような方へ向けて書かれた記事となります

「SQL言語で条件分岐がしたい」

「CASEの使い方がわからない」

「CASEで何ができるのだろうか」

✔当記事を通じてお伝えすること

  • CASEとは
  • CASEの書き方
  • CASEでできること

当記事では、SQL言語のCASEについて、基本的な書き方はもちろん、応用した使い方まで丁寧に解説していきます。

ぜひ最後までご覧ください。

✔当記事の信頼性

当記事では、Python言語をベースとしたDjangoフレームワークで、アプリの公開方法をご紹介しています。

データの保存場所は、サーバー内で動くpostgreSQL(ポスグレ)です。

Djangoを使えばSQLをマスターしておく必要はないものの、最低限の知識として、かなり勉強しました。

実際のコードや写真付きで、できる限り丁寧に解説します。

※Djangoのチュートリアルはこちら。

created by Rinker
¥2,838 (2024/10/05 22:17:08時点 楽天市場調べ-詳細)
SQL学習におすすめ

筆者プロフィール

筆者プロフィールアイコン

【現職】プロダクトマネージャー

【副業】ブログ(月間20万PV)/YouTube/Web・アプリ制作

「プログラミング × ライティング × 営業」の経験を活かし、30後半からのIT系職へシフト。現在はプロダクトマネージャーとして、さまざまな関係者の間に入り奮闘してます。当サイトでは、実際に手を動かせるWebアプリの開発を通じて、プログラミングはもちろん、IT職に必要な情報を提供していきます。

【当ブログで紹介しているサイト】

当サイトチュートリアルで作成したデモ版日報アプリ

Django × Reactで開発したツール系Webアプリ

✔人に見せても恥ずかしくないコードを書こう

「リーダブルコード」は、わかりやすく良いコードの定義を教えてくれる本です。

  • 見るからにきれいなコードの書き方
  • コードの分割方法
  • 変数や関数の命名規則

エンジニアのスタンダートとすべき基準を一から解説しています。

何回も読むのに値する本なので、ぜひ手にとって読んでみてください。

【SQL】CASEで知っておくべき基礎事項

CASEを学ぶための必須事項を見ていきます。

応用した使い方まで知るためにも、必ず目を通しておきましょう。

  • SQLとは
  • CASE文の概要
  • CASE文とIF文の違い

SQLとは

SQL(Structured Query Language)は、リレーショナルデータベース管理システム(RDBMS)でデータ操作や定義、制御を行うための標準的な言語です。

データベースに対する以下のような操作ができる言語になります。

  • データの検索
  • データの更新
  • データ削除
  • テーブルの作成や変更

CASE文の概要

CASE文は、SQLクエリ内で条件分岐を実現する強力なツールです。

それは複数の条件を評価し、各条件に対応する結果を返します。

以下の例では、顧客の年齢に基づいて年齢グループを割り当てます。

SELECT customer_id, age,
       CASE
  WHEN age < 20 THEN 'Teen'
  WHEN age BETWEEN 20 AND 64 THEN 'Adult'
  WHEN age >= 65 THEN 'Senior'
  ELSE 'Unknown'
       END as age_group
FROM customers;

この例では、CASE文が3つの異なる条件を評価して、それぞれに対応する結果を返しています。

顧客の年齢対応する結果
20歳未満‘Teen’
20歳から64歳‘Adult’
65歳以上‘Senior’

どの条件も満たされない場合、ELSE句が使われ、’Unknown’が返されます。

CASE文とIF文の違い

CASE文とIF文は両方とも条件に基づいた結果を返すための制御フロー構造ですが、その使い方と適用範囲にはいくつかの重要な違いがあります。

  1. CASEでは複数の条件で結果を返せる
  2. IF文は、サポートされていないシステムもある

CASEでは複数の条件で結果を返せる

CASE文は複数の条件を照らし合わせて結果を返すのに対し、IF文は単一の条件を評価して結果を返します。

以下にMySQLのIF文の例を示します。

SELECT customer_id, age,
       IF(age < 20, 'Teen', 'Non-teen') as age_group
FROM customers;

このクエリは、もし顧客の年齢が20歳未満ならば’Teen’を返し、そうでなければ’Non-teen’を返します。

複数の条件を評価するためには、複数のIF文をネストする必要があります。

IF文は、サポートされていないシステムもある

CASE文はSQL標準であり、ほとんどのリレーショナルデータベース管理システム(RDBMS)でサポートされています。

一方、IF文はデータベースによります。

例えばPostgreSQLでは、条件式にCASE文が推奨されています。

条件式

これらの違いを理解することで、特定の状況やデータベースシステムに最適な選択を行うことができます

CASE文の基本構文

CASE文の基本構文をご覧ください。

文法として、どのような順番で書くかをおさえましょう。

  • 単純CASE式
  • 検索CASE式
  • CASE文の注意点
  • CASE文とNULLの取り扱い

 単純CASE式

単純CASE式は、ある列の値に応じて結果を返すものです。

SELECT 列1, 列2,

       CASE 列3

   WHEN 条件1(値1) THEN 出力結果1

   WHEN 条件2(値2) THEN 出力結果2

   WHEN 条件3(値3) THEN 出力結果3

   ELSE 出力結果4(上の条件に満たないときの出力結果4)

      END as 結果セットの列名

FROM データを操作するテーブル名;

以下に例を示します。

SELECT customer_id, total_purchase,
       CASE membership_level
WHEN 'Bronze' THEN 'Low'
WHEN 'Silver' THEN 'Medium'
WHEN 'Gold' THEN 'High'
ELSE 'Unknown'
       END as membership_category
FROM customers;

試してみたい方はこちらでテーブルを作って試してみよう。

SQL Fiddle - Online SQL Compiler for learning & practice
Discover our free online SQL editor enhanced with AI to chat, explain, and generate code. Support SQL Server, MySQL, Mar...
CREATE TABLE customers (
    customer_id INT PRIMARY KEY,
    total_purchase DECIMAL(10,2),
    membership_level VARCHAR(10)
);

INSERT INTO customers (customer_id, total_purchase, membership_level)
VALUES (1, 100.00, 'Bronze'),
       (2, 200.00, 'Silver'),
       (3, 300.00, 'Gold'),
       (4, 400.00, 'Bronze'),
       (5, 500.00, 'Platinum');

出力結果

customer_idtotal_purchasemembership_category
1100Low
2200Medium
3300High
4400Low
5500Unknown

検索CASE式

検索CASE式は、複数の条件を評価して結果を返します。

以下がその例です。

SELECT customer_id, age,
       CASE
WHEN age < 20 THEN 'Teenager'
WHEN age BETWEEN 20 AND 64 THEN 'Adult'
WHEN age >= 65 THEN 'Senior'
ELSE 'Unknown'
       END as age_group
FROM customers;

CASE文の注意点

CASE文で覚えておくべき注意点は以下のとおりです。

  • 必ずENDキーワードを使用する: ENDがないと、SQLはCASE文がどこで終了するのかを知らないため、エラーが発生
  • ELSE句の使用: CASE文の中にある条件のいずれも満たされない場合、SQLは何をすべきかを知らないため、意図しない結果を返す可能性がある
  • ネストしたCASE文の扱い: CASE文は他のCASE文の中にネストできるが、適切なインデントとカッコを使用して可読性を保つようにする
  • 順序の重要性: CASE文は上から順に評価され、最初に真となる条件が結果を決定するため、順番に気を付ける
  • NULL値の取り扱い: CASE文では、評価される式がNULLの場合、その条件は偽と評価される
  • パフォーマンスへの影響: 特に大きなテーブルで複雑なCASE文を使用すると、パフォーマンスが低下する可能性がある

CASE文とNULLの取り扱い

CASE文でNULL値を扱う場合は、IS NULLまたはIS NOT NULL演算子を使用します。

以下に例を示します。

SELECT product_id, price,
       CASE
WHEN price IS NULL THEN 'Not available'
ELSE
'Available'
       END as availability
FROM products;

実践的な例で学ぶCASE文

実践ではどのように使われているのかをご紹介します。

具体例を見て、使いたいケースに近いものを探しましょう。

  • 成績の評価を行う例
  • カテゴリ別の売上集計を行う例
  • データの欠損値を補完する例

成績の評価を行う例

以下の例では、学生の得点に基づいて成績を評価しています。

CASE文例

SELECT student_id, 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;

テーブル作成のSQL

こちらでテーブルを作り試してみました。

SQL Fiddle - Online SQL Compiler for learning & practice
Discover our free online SQL editor enhanced with AI to chat, explain, and generate code. Support SQL Server, MySQL, Mar...
CREATE TABLE students (
    student_id INT PRIMARY KEY,
    score INT
);

INSERT INTO students (student_id, score)
VALUES (1, 95),
       (2, 85),
       (3, 75),
       (4, 65),
       (5, 55);

出力結果

student_idscoregrade
195A
285B
375C
465D
555F

カテゴリ別の売上集計を行う例

以下の例では、商品カテゴリごとに売上を集計しています。

CASE文例

SELECT category,
       SUM(CASE WHEN month = 'Jan' THEN sales ELSE 0 END) as Jan_sales,
       SUM(CASE WHEN month = 'Feb' THEN sales ELSE 0 END) as Feb_sales,
       SUM(CASE WHEN month = 'Mar' THEN sales ELSE 0 END) as Mar_sales,
       SUM(CASE WHEN month = 'Apr' THEN sales ELSE 0 END) as Apr_sales
FROM sales_data
GROUP BY category;

テーブル作成のSQL

テーブルはこちらで作りましょう。

CREATE TABLE sales_data (
    category VARCHAR(20),
    month VARCHAR(3),
    sales DECIMAL(10,2)
);

INSERT INTO sales_data (category, month, sales)
VALUES ('Electronics', 'Jan', 1000.00),
       ('Electronics', 'Feb', 1500.00),
       ('Electronics', 'Mar', 1200.00),
       ('Electronics', 'Apr', 1300.00),
       ('Furniture', 'Jan', 900.00),
       ('Furniture', 'Feb', 700.00),
       ('Furniture', 'Mar', 800.00),
       ('Furniture', 'Apr', 1000.00);

出力結果

categoryJan_salesFeb_salesMar_salesApr_sales
Electronics1000150012001300
Furniture9007008001000

データの欠損値を補完する例

以下の例では、価格がNULLの場合に平均価格で補完しています。

文例

SELECT product_id,
       COALESCE(price, (SELECT AVG(price) FROM products WHERE price IS NOT NULL)) as adjusted_price
FROM products;

テーブル作成のSQL

CREATE TABLE products (
    product_id INT PRIMARY KEY,
    price DECIMAL(10,2)
);

INSERT INTO products (product_id, price)
VALUES (1, 100.00),
       (2, 200.00),
       (3, NULL),
       (4, 400.00),
       (5, NULL);

出力結果

product_idadjusted_price
1100
2200
3233.333333
4400
5233.333333

CASE文を使った応用例

CASE文を使った応用例も見ていきましょう。

CASEを使うだけでなく、ほかの処理とも組み合わせていきます。

  • CASE文を使ったソート
  • CASE文を使った集計
  • CASE文を使ったデータの更新
  • CASE文を使った条件付き結合

CASE文を使ったソート

以下の例では、CASE文を使って特定の条件でソートしています。

SELECT customer_id, total_purchase, membership_level
FROM customers
ORDER BY CASE membership_level
  WHN 'Gold' THEN 1
  WHEN 'Silver' THEN 2
  WHEN 'Bronze' THEN 3
  ELSE 4
END;

CASE文を使った集計

以下の例では、性別と年齢層ごとの顧客数を集計しています。

SELECT gender,
       COUNT(CASE
      WHEN age < 20 THEN 1
      ELSE NULL
    END) as teenagers,
       COUNT(CASE
      WHEN age BETWEEN 20 AND 64 THEN 1
      ELSE NULL
    END) as adults,
       COUNT(CASE
      WHEN age >= 65 THEN 1
      ELSE NULL
    END) as seniors
FROM customers
GROUP BY gender;

CASE文を使ったデータの更新

以下の例では、在庫が一定数以下の場合に注文ステータスを更新しています。

UPDATE orders
SET order_status = CASE
   WHEN stock <= 10 THEN 'Low Stock'
   ELSE 'In Stock'
 END;

CASE文を使った条件付き結合

以下の例では、CASE文を使って顧客の会員レベルに応じて異なるディスカウントテーブルと結合しています。

SELECT c.customer_id, c.membership_level, p.product_id, p.price,
       p.price * d.discount_rate as discounted_price
FROM customers c
JOIN products p
JOIN discounts d ON d.discount_id =
  CASE c.membership_level
    WHEN 'Gold' THEN p.gold_discount_id
    WHEN 'Silver' THEN p.silver_discount_id
    WHEN 'Bronze' THEN p.bronze_discount_id
    ELSE p.default_discount_id
  END;

CASE文のパフォーマンスに関する注意点

CASE文を扱うにあたって、気を付けるべき点とその対処法を見ていきます。

うまくいかないときのために、事前に調べておきましょう。

  • 結果の選択肢が多い場合の対処法
  • インデックスの活用
  • 最適化ヒントの活用

結果の選択肢が多い場合の対処法

CASE文を使って複数の選択肢を評価すると、特に選択肢の数が多い場合、パフォーマンスが低下する可能性があります。

解決策としては、サブクエリやテーブル結合を使用して問題を回避する方法が挙げられます。

例えば、次のようなCASE文があるとします。

SELECT product_id,
       CASE product_id
         WHEN 1 THEN 'Product 1'
         WHEN 2 THEN 'Product 2'
         -- ... hundreds or thousands more options ...
         WHEN 10000 THEN 'Product 10000'
         ELSE 'Unknown Product'
       END as product_name
FROM products;

これは、商品IDが1から10,000までの各商品に対応する商品名を取得しようとしています。

しかし、選択肢が多いため、このクエリは効率的ではありません。

代わりに、別のテーブル(たとえば`product_names`)を作成し、商品IDと商品名をマッピングすることができます。

CREATE TABLE product_names (
    product_id INT PRIMARY KEY,
    product_name VARCHAR(100)
);

そして、このテーブルを元の`products`テーブルと結合することで、同じ結果を得られるのです。

SELECT p.product_id,
       COALESCE(n.product_name, 'Unknown Product') as product_name
FROM products p
LEFT JOIN product_names n ON p.product_id = n.product_id;

このクエリでは、商品IDに対応する商品名が`product_names`テーブルに存在しない場合、’Unknown Product’が使用されます。

これにより、CASE文を使用するよりも効率的に商品名を取得できます。

インデックスの活用

CASE文が検索条件に含まれる場合、インデックスの利用が制限されることがあります。

インデックスを効果的に活用するために、検索条件を工夫するか、CASE文を使わない方法を検討してください。

最適化ヒントの活用

データベースによっては、最適化ヒントを使用してクエリプランを調整することができます。パフォーマンス問題が発生した場合、最適化ヒントの活用を検討してください。

無料SQLツール:SQL Fiddle

当記事で共有している写真も、SQL Fiddleを使ってご説明しました。

特徴は以下のとおり。

  • SQL言語がブラウザ打てて、実行できる
  • 完全無料
  • 登録不要

以下のように、左側でテーブルやカラムの設定をおこない、右側でコードが実行できるのです。

SQL言語を学ぶなら、登録してくことをおすすめします!

ちなみに今回のデータベース設定として、SQL Fiddleの左側に書いたコードはこちら。

CREATE TABLE players_2022(
  id SERIAL primary key,
  name varchar(50),
  score integer
);

CREATE TABLE players_all_time(
  id SERIAL primary key,
  name varchar(50),
  score integer
);

INSERT INTO players_2022 (name, score) VALUES ('エンバペ', 8);
INSERT INTO players_2022 (name, score) VALUES ('メッシ', 7);
INSERT INTO players_2022 (name, score) VALUES ('ジルー', 4);
INSERT INTO players_2022 (name, score) VALUES ('アルバレス', 4);
INSERT INTO players_2022 (name, score) VALUES ('バレンシア', 3);
INSERT INTO players_2022 (name, score) VALUES ('ガクポ', 3);
INSERT INTO players_2022 (name, score) VALUES ('西藤', 1);

INSERT INTO players_all_time (name, score) VALUES ('クローゼ', 16);
INSERT INTO players_all_time (name, score) VALUES ('ロナウド', 15);
INSERT INTO players_all_time (name, score) VALUES ('ミュラー', 14);
INSERT INTO players_all_time (name, score) VALUES ('フォンテーヌ', 13);
INSERT INTO players_all_time (name, score) VALUES ('西藤', 3);

コピーして活用してください。

まとめ

当記事でお伝えしてきたことはこちら。

  • CASE文の基本構文
  • 実践的な例
  • 応用例
  • パフォーマンスに関する注意点

CASE文により、条件に応じて値を返す柔軟なクエリを作成できます。

今回学んだ知識を活かして、実際のデータベースでCASE文を使ったクエリを作成してみてください。

また、他のSQL機能やデータベース管理に関する知識も学び、スキルをさらに磨いていきましょう。

タイトルとURLをコピーしました