— 間違い: すべて「低価格」になってしまう
CASE
WHEN price >= 100 THEN ‘低価格’ — ほぼ全部ここに当てはまる!
WHEN price >= 500 THEN ‘中価格’ — 評価されない
WHEN price >= 1000 THEN ‘高価格’ — 評価されない
END
✅ 正しい順序(厳しい条件が先):
※横にスクロールできます
— 正しい: 厳しい条件を先に
CASE
WHEN price >= 1000 THEN ‘高価格’ — 1000以上だけ
WHEN price >= 500 THEN ‘中価格’ — 500以上1000未満
ELSE ‘低価格’ — 500未満
END
SELECT
product_name,
price,
CASE
WHEN price >= 1000 THEN ‘高価格’
WHEN price >= 500 THEN ‘中価格’
ELSE ‘低価格’
END AS price_category
FROM products
ORDER BY price DESC
LIMIT 10;
クエリの解説:
CASE ... END → CASE式全体
WHEN price >= 1000 THEN '高価格' → 1000円以上なら「高価格」
WHEN price >= 500 THEN '中価格' → 500円以上1000円未満なら「中価格」
ELSE '低価格' → それ以外(500円未満)は「低価格」
AS price_category → CASE式の結果に列名をつける
結果イメージ:
product_name
price
price_category
高級メロン
5,000
高価格
まぐろ
3,000
高価格
ぶどう
500
中価格
りんご
150
低価格
バナナ
120
低価格
3-2. 例2:在庫状況を判定する
やりたいこと:在庫数に応じて「在庫切れ」「在庫少」「通常」「在庫豊富」を表示する
※横にスクロールできます
SELECT
product_name,
stock,
CASE
WHEN stock = 0 THEN ‘在庫切れ’
WHEN stock < 10 THEN '在庫少'
WHEN stock < 50 THEN '通常'
ELSE '在庫豊富'
END AS stock_status
FROM products
ORDER BY stock;
ポイント:
stock = 0 を最初に書く(最も厳しい条件)
stock < 10 は「1〜9」に当てはまる(0は除外済み)
stock < 50 は「10〜49」に当てはまる
ELSE は「50以上」に当てはまる
3-3. CASE式が使える場所
CASE式は SELECT句だけでなく、様々な場所で使えます。
📌 CASE式が使える場所
場所
用途
例
SELECT句
新しい列を作る
CASE ... END AS 列名
WHERE句
条件で絞り込み
WHERE CASE ... END = '値'
ORDER BY句
動的な並び替え
ORDER BY CASE ... END
GROUP BY句
条件でグループ化
GROUP BY CASE ... END
集計関数内
条件付き集計
SUM(CASE ... END)
3-4. 例3:ORDER BYでCASE式を使う
やりたいこと:在庫切れを最優先で表示する(通常の数値順ではなく)
※横にスクロールできます
SELECT
product_name,
stock,
CASE
WHEN stock = 0 THEN '在庫切れ'
WHEN stock < 10 THEN '在庫少'
ELSE '正常'
END AS stock_status
FROM products
ORDER BY
CASE
WHEN stock = 0 THEN 1 -- 在庫切れを1番に
WHEN stock < 10 THEN 2 -- 在庫少を2番に
ELSE 3 -- 正常を3番に
END,
product_name;
ポイント:
ORDER BY でCASE式を使うと、優先度順に並び替えできる
数値(1, 2, 3)を返すことで順序を制御
同じ優先度内では product_name でソート
🔍 4. 検索CASE式(自由な条件を書ける)
4-1. 検索CASE式とは
検索CASE式は、各 WHEN で自由な条件式を書けるタイプです。これが最も一般的に使われる形です。
📌 検索CASE式の構文
※横にスクロールできます
CASE
WHEN 条件式1 THEN 結果1
WHEN 条件式2 THEN 結果2
WHEN 条件式3 THEN 結果3
ELSE デフォルト値
END
SELECT
order_id,
order_date,
CASE
WHEN strftime('%m', order_date) IN ('12', '01', '02') THEN '冬'
WHEN strftime('%m', order_date) IN ('03', '04', '05') THEN '春'
WHEN strftime('%m', order_date) IN ('06', '07', '08') THEN '夏'
ELSE '秋'
END AS season
FROM orders
ORDER BY order_date DESC
LIMIT 10;
クエリの解説:
strftime('%m', order_date) → 日付から月を抽出('01'〜'12')
IN ('12', '01', '02') → 12月、1月、2月のいずれか
複数の値をまとめて判定するのに IN が便利
4-3. 例2:顧客ランクを判定する
やりたいこと:顧客の総購入額でランクを判定する
コードを段階的に見ていきましょう。
ステップ1:顧客ごとの総購入額を計算
※横にスクロールできます
SELECT
c.customer_id,
c.customer_name,
SUM(o.total_amount) AS total_purchase
FROM customers c
LEFT JOIN orders o ON c.customer_id = o.customer_id
GROUP BY c.customer_id, c.customer_name
ステップ2:総購入額でランクを判定
※横にスクロールできます
CASE
WHEN SUM(o.total_amount) >= 100000 THEN 'プラチナ'
WHEN SUM(o.total_amount) >= 50000 THEN 'ゴールド'
WHEN SUM(o.total_amount) >= 10000 THEN 'シルバー'
ELSE 'ブロンズ'
END AS customer_rank
ポイント:
CASE式の条件に集計関数(SUM)を使える
厳しい条件(>= 100000)を先に書く
完成コード:
※横にスクロールできます
SELECT
c.customer_name AS 顧客名,
COALESCE(SUM(o.total_amount), 0) AS 総購入額,
CASE
WHEN SUM(o.total_amount) >= 100000 THEN 'プラチナ'
WHEN SUM(o.total_amount) >= 50000 THEN 'ゴールド'
WHEN SUM(o.total_amount) >= 10000 THEN 'シルバー'
ELSE 'ブロンズ'
END AS 顧客ランク
FROM customers c
LEFT JOIN orders o ON c.customer_id = o.customer_id
GROUP BY c.customer_id, c.customer_name
ORDER BY 総購入額 DESC NULLS LAST;
結果イメージ:
顧客名
総購入額
顧客ランク
山田太郎
150,000
プラチナ
鈴木花子
75,000
ゴールド
田中次郎
25,000
シルバー
佐藤美咲
5,000
ブロンズ
4-4. 例3:複数条件を組み合わせる
やりたいこと:在庫と価格を組み合わせて優先度を判定する
※横にスクロールできます
SELECT
product_name AS 商品名,
price AS 価格,
stock AS 在庫,
CASE
WHEN stock = 0 THEN '販売停止'
WHEN stock < 5 AND price >= 1000 THEN '高級品・要補充'
WHEN stock < 10 THEN '補充推奨'
WHEN stock > 100 THEN '過剰在庫注意'
ELSE '正常'
END AS ステータス
FROM products
ORDER BY stock;
CASE 列名
WHEN 値1 THEN 結果1
WHEN 値2 THEN 結果2
WHEN 値3 THEN 結果3
ELSE デフォルト値
END
CASE の直後に列名を書き、各 WHEN で値だけを書きます。
5-2. 検索CASE式と単純CASE式の比較
同じ処理を両方で書いた場合:
検索CASE式
単純CASE式
CASE WHEN category = 'fruit' THEN '果物' WHEN category = 'vegetable' THEN '野菜' ELSE 'その他' END
CASE category WHEN 'fruit' THEN '果物' WHEN 'vegetable' THEN '野菜' ELSE 'その他' END
単純CASE式の方が短く書けます。category = を省略できます。
5-3. 例1:カテゴリを日本語に変換
やりたいこと:英語のカテゴリコードを日本語に変換する
※横にスクロールできます
SELECT
product_name AS 商品名,
category AS カテゴリコード,
CASE category
WHEN 'fruit' THEN '果物'
WHEN 'vegetable' THEN '野菜'
WHEN 'meat' THEN '肉類'
WHEN 'fish' THEN '魚類'
ELSE 'その他'
END AS カテゴリ名
FROM products
LIMIT 10;
結果イメージ:
商品名
カテゴリコード
カテゴリ名
りんご
fruit
果物
バナナ
fruit
果物
キャベツ
vegetable
野菜
牛肉
meat
肉類
5-4. 例2:曜日番号を曜日名に変換
やりたいこと:strftime('%w')で得られる曜日番号(0-6)を曜日名に変換する
※横にスクロールできます
SELECT
order_date AS 注文日,
strftime('%w', order_date) AS 曜日番号,
CASE strftime('%w', order_date)
WHEN '0' THEN '日曜日'
WHEN '1' THEN '月曜日'
WHEN '2' THEN '火曜日'
WHEN '3' THEN '水曜日'
WHEN '4' THEN '木曜日'
WHEN '5' THEN '金曜日'
WHEN '6' THEN '土曜日'
END AS 曜日名
FROM orders
ORDER BY order_date DESC
LIMIT 7;
ポイント:
strftime('%w', order_date) → 曜日番号('0'=日曜〜'6'=土曜)
戻り値は文字列なので、WHEN も '0' のように文字列で比較
ELSEがなくても、0-6のすべてをカバーしているのでOK
5-5. 例3:ステータスコードを文字に変換
やりたいこと:数値のステータスコードを人間が読める形に変換する
※横にスクロールできます
SELECT
order_id AS 注文ID,
status AS ステータスコード,
CASE status
WHEN 0 THEN '未処理'
WHEN 1 THEN '処理中'
WHEN 2 THEN '発送済'
WHEN 3 THEN '配達完了'
WHEN 9 THEN 'キャンセル'
ELSE '不明'
END AS ステータス名
FROM orders
LIMIT 10;
SELECT
グループ化する列,
SUM(CASE WHEN 条件1 THEN 値 ELSE 0 END) AS 列名1,
SUM(CASE WHEN 条件2 THEN 値 ELSE 0 END) AS 列名2,
SUM(CASE WHEN 条件3 THEN 値 ELSE 0 END) AS 列名3
FROM テーブル
GROUP BY グループ化する列;
ポイント: 「条件に合う場合だけ値を足す、合わない場合は0」という処理を列ごとに行います。
7-3. 例1:月別売上を横に並べる
やりたいこと:2024年の1月〜6月の売上を列に展開する
コードを段階的に見ていきましょう。
ステップ1:1月の売上だけを取り出す
※横にスクロールできます
SUM(CASE WHEN strftime('%m', order_date) = '01' THEN total_amount ELSE 0 END) AS 一月
解説:
strftime('%m', order_date) = '01' → 1月の場合
THEN total_amount → 売上金額を返す
ELSE 0 → 1月以外は0
SUM(...) → 1月の売上だけが合計される
ステップ2:2月〜6月も同様に
※横にスクロールできます
SUM(CASE WHEN strftime('%m', order_date) = '02' THEN total_amount ELSE 0 END) AS 二月,
SUM(CASE WHEN strftime('%m', order_date) = '03' THEN total_amount ELSE 0 END) AS 三月,
-- 以下同様...
完成コード:
※横にスクロールできます
SELECT
strftime('%Y', order_date) AS 年,
SUM(CASE WHEN strftime('%m', order_date) = '01' THEN total_amount ELSE 0 END) AS 一月,
SUM(CASE WHEN strftime('%m', order_date) = '02' THEN total_amount ELSE 0 END) AS 二月,
SUM(CASE WHEN strftime('%m', order_date) = '03' THEN total_amount ELSE 0 END) AS 三月,
SUM(CASE WHEN strftime('%m', order_date) = '04' THEN total_amount ELSE 0 END) AS 四月,
SUM(CASE WHEN strftime('%m', order_date) = '05' THEN total_amount ELSE 0 END) AS 五月,
SUM(CASE WHEN strftime('%m', order_date) = '06' THEN total_amount ELSE 0 END) AS 六月,
SUM(total_amount) AS 合計
FROM orders
WHERE strftime('%Y', order_date) = '2024'
GROUP BY strftime('%Y', order_date);
結果イメージ:
年
一月
二月
三月
四月
五月
六月
合計
2024
1,000,000
1,200,000
1,500,000
1,800,000
1,600,000
2,000,000
9,100,000
7-4. 例2:カテゴリ別売上のピボット
やりたいこと:月ごとに、カテゴリ別の売上を列に展開する
※横にスクロールできます
SELECT
strftime('%Y-%m', o.order_date) AS 年月,
SUM(CASE WHEN p.category = '果物' THEN o.total_amount ELSE 0 END) AS 果物,
SUM(CASE WHEN p.category = '野菜' THEN o.total_amount ELSE 0 END) AS 野菜,
SUM(CASE WHEN p.category = '肉類' THEN o.total_amount ELSE 0 END) AS 肉類,
SUM(o.total_amount) AS 合計
FROM orders o
JOIN products p ON o.product_id = p.product_id
GROUP BY strftime('%Y-%m', o.order_date)
ORDER BY 年月 DESC
LIMIT 6;
結果イメージ:
年月
果物
野菜
肉類
合計
2024-06
50,000
30,000
80,000
160,000
2024-05
45,000
28,000
75,000
148,000
2024-04
40,000
25,000
70,000
135,000
📊 8. 条件付き集計
8-1. SUM + CASE:条件付き合計
SUM(CASE ...) を使うと、特定の条件を満たす値だけを合計できます。
例:平日と週末の売上を別々に集計
※横にスクロールできます
SELECT
strftime('%Y-%m', order_date) AS 年月,
SUM(total_amount) AS 総売上,
SUM(CASE
WHEN strftime('%w', order_date) NOT IN ('0', '6')
THEN total_amount ELSE 0
END) AS 平日売上,
SUM(CASE
WHEN strftime('%w', order_date) IN ('0', '6')
THEN total_amount ELSE 0
END) AS 週末売上
FROM orders
GROUP BY strftime('%Y-%m', order_date)
ORDER BY 年月 DESC
LIMIT 6;
クエリの解説:
strftime('%w', order_date) → 曜日番号('0'=日曜、'6'=土曜)
NOT IN ('0', '6') → 日曜・土曜以外 = 平日
IN ('0', '6') → 日曜・土曜 = 週末
8-2. COUNT + CASE:条件付きカウント
SUM(CASE WHEN 条件 THEN 1 ELSE 0 END) で、条件を満たす行数をカウントできます。
例:カテゴリごとの価格帯別商品数
※横にスクロールできます
SELECT
category AS カテゴリ,
COUNT(*) AS 総商品数,
SUM(CASE WHEN price >= 1000 THEN 1 ELSE 0 END) AS 高価格商品数,
SUM(CASE WHEN price >= 500 AND price < 1000 THEN 1 ELSE 0 END) AS 中価格商品数,
SUM(CASE WHEN price < 500 THEN 1 ELSE 0 END) AS 低価格商品数
FROM products
GROUP BY category
ORDER BY 総商品数 DESC;
ポイント:
THEN 1 ELSE 0 → 条件に合えば1、合わなければ0
SUM(...) → 1を合計 = 条件に合う件数
これで「高価格商品が何個あるか」をカウントできる
結果イメージ:
カテゴリ
総商品数
高価格商品数
中価格商品数
低価格商品数
果物
20
5
8
7
野菜
15
2
5
8
肉類
10
8
2
0
8-3. 比率の計算
やりたいこと:週末売上が全体の何%かを計算する
※横にスクロールできます
SELECT
strftime('%Y-%m', order_date) AS 年月,
SUM(total_amount) AS 総売上,
SUM(CASE
WHEN strftime('%w', order_date) IN ('0', '6')
THEN total_amount ELSE 0
END) AS 週末売上,
ROUND(
SUM(CASE
WHEN strftime('%w', order_date) IN ('0', '6')
THEN total_amount ELSE 0
END) * 100.0 / SUM(total_amount),
1
) AS 週末比率
FROM orders
GROUP BY strftime('%Y-%m', order_date)
ORDER BY 年月 DESC
LIMIT 6;
比率の計算式:
週末比率 = 週末売上 ÷ 総売上 × 100
* 100.0 で小数計算にし、ROUND(..., 1) で小数点1桁に丸めています。
8-4. 例:達成率の計算と評価
やりたいこと:月次売上の目標達成率を計算し、達成状況を評価する
※横にスクロールできます
WITH monthly_sales AS (
SELECT
strftime('%Y-%m', order_date) AS year_month,
SUM(total_amount) AS actual
FROM orders
GROUP BY strftime('%Y-%m', order_date)
),
targets AS (
SELECT '2024-01' AS year_month, 1000000 AS target
UNION ALL SELECT '2024-02', 1200000
UNION ALL SELECT '2024-03', 1500000
UNION ALL SELECT '2024-04', 1800000
)
SELECT
t.year_month AS 年月,
t.target AS 目標,
COALESCE(ms.actual, 0) AS 実績,
ROUND(COALESCE(ms.actual, 0) * 100.0 / t.target, 1) AS 達成率,
CASE
WHEN COALESCE(ms.actual, 0) >= t.target THEN '✅ 達成'
WHEN COALESCE(ms.actual, 0) >= t.target * 0.9 THEN '🟡 惜しい'
WHEN COALESCE(ms.actual, 0) >= t.target * 0.8 THEN '🟠 要努力'
ELSE '❌ 大幅未達'
END AS 評価
FROM targets t
LEFT JOIN monthly_sales ms ON t.year_month = ms.year_month
ORDER BY t.year_month;
結果イメージ:
年月
目標
実績
達成率
評価
2024-01
1,000,000
1,050,000
105.0%
✅ 達成
2024-02
1,200,000
1,100,000
91.7%
🟡 惜しい
2024-03
1,500,000
1,250,000
83.3%
🟠 要努力
2024-04
1,800,000
1,200,000
66.7%
❌ 大幅未達
活用シーン:
営業レポート:売上目標の達成状況
KPI管理:指標の達成・未達を自動判定
ダッシュボード:視覚的な評価表示
💼 9. 実務での活用パターン
9-1. パターン1:在庫アラートの生成
やりたいこと:在庫状況に応じたアラートメッセージを表示する
※横にスクロールできます
SELECT
product_name AS 商品名,
stock AS 在庫,
CASE
WHEN stock = 0 THEN '🔴 緊急: 在庫切れ'
WHEN stock <= 5 THEN '🟡 警告: 在庫僅少(' || stock || '個)'
WHEN stock <= 20 THEN '🟢 注意: 在庫少なめ'
ELSE '✅ 正常'
END AS アラート,
CASE
WHEN stock = 0 THEN '即時発注'
WHEN stock <= 5 THEN '至急発注'
WHEN stock <= 20 THEN '発注検討'
ELSE 'なし'
END AS 推奨アクション
FROM products
ORDER BY stock, product_name;
ポイント:
|| stock || → 文字列連結で在庫数をメッセージに埋め込み
絵文字を使って視覚的に分かりやすく
アラートとアクションを別の列で表示
9-2. パターン2:会員ランクに応じた割引計算
やりたいこと:顧客の総購入額に応じて割引率を変え、割引後価格を計算する
※横にスクロールできます
WITH customer_totals AS (
SELECT
customer_id,
SUM(total_amount) AS total_purchase
FROM orders
GROUP BY customer_id
)
SELECT
c.customer_name AS 顧客名,
o.order_id AS 注文ID,
o.total_amount AS 通常価格,
CASE
WHEN ct.total_purchase >= 100000 THEN 'プラチナ(15%OFF)'
WHEN ct.total_purchase >= 50000 THEN 'ゴールド(10%OFF)'
WHEN ct.total_purchase >= 10000 THEN 'シルバー(5%OFF)'
ELSE 'ブロンズ(割引なし)'
END AS 会員ランク,
ROUND(o.total_amount * (1 - CASE
WHEN ct.total_purchase >= 100000 THEN 0.15
WHEN ct.total_purchase >= 50000 THEN 0.10
WHEN ct.total_purchase >= 10000 THEN 0.05
ELSE 0
END)) AS 割引後価格
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id
JOIN customer_totals ct ON o.customer_id = ct.customer_id
ORDER BY o.order_date DESC
LIMIT 10;
ポイント:
CTEで顧客の総購入額を事前に計算
CASE式を2回使用(ランク表示用と計算用)
1 - 割引率 で割引後価格を計算
9-3. パターン3:都道府県別の顧客ランク分布
やりたいこと:都道府県ごとに、顧客ランクの人数分布を横に展開する
コードを段階的に見ていきましょう。
ステップ1:各顧客のランクを判定
※横にスクロールできます
WITH customer_ranks AS (
SELECT
c.prefecture,
c.customer_id,
CASE
WHEN SUM(o.total_amount) >= 100000 THEN 'VIP'
WHEN SUM(o.total_amount) >= 50000 THEN '優良'
ELSE '一般'
END AS rank
FROM customers c
LEFT JOIN orders o ON c.customer_id = o.customer_id
GROUP BY c.prefecture, c.customer_id
)
ステップ2:都道府県ごとにピボット変換
※横にスクロールできます
SELECT
prefecture AS 都道府県,
COUNT(*) AS 総顧客数,
SUM(CASE WHEN rank = 'VIP' THEN 1 ELSE 0 END) AS VIP,
SUM(CASE WHEN rank = '優良' THEN 1 ELSE 0 END) AS 優良,
SUM(CASE WHEN rank = '一般' THEN 1 ELSE 0 END) AS 一般
FROM customer_ranks
GROUP BY prefecture
完成コード:
※横にスクロールできます
WITH customer_ranks AS (
SELECT
c.prefecture,
c.customer_id,
CASE
WHEN SUM(o.total_amount) >= 100000 THEN 'VIP'
WHEN SUM(o.total_amount) >= 50000 THEN '優良'
ELSE '一般'
END AS rank
FROM customers c
LEFT JOIN orders o ON c.customer_id = o.customer_id
GROUP BY c.prefecture, c.customer_id
)
SELECT
prefecture AS 都道府県,
COUNT(*) AS 総顧客数,
SUM(CASE WHEN rank = 'VIP' THEN 1 ELSE 0 END) AS VIP,
SUM(CASE WHEN rank = '優良' THEN 1 ELSE 0 END) AS 優良,
SUM(CASE WHEN rank = '一般' THEN 1 ELSE 0 END) AS 一般
FROM customer_ranks
GROUP BY prefecture
ORDER BY 総顧客数 DESC
LIMIT 10;
結果イメージ:
都道府県
総顧客数
VIP
優良
一般
東京都
150
20
45
85
大阪府
80
10
25
45
神奈川県
60
8
18
34
📝 練習問題
CASE式をマスターしましょう!
問題 1基本
価格で分類
商品を価格で「高価格」(500円以上)、「低価格」(500円未満)に分類してください。
※横にスクロールできます
SELECT
product_name AS 商品名,
price AS 価格,
CASE
WHEN price >= 500 THEN '高価格'
ELSE '低価格'
END AS 価格帯
FROM products
ORDER BY price DESC;
SELECT
product_name AS 商品名,
stock AS 在庫数,
CASE
WHEN stock = 0 THEN '在庫切れ'
WHEN stock < 10 THEN '在庫少'
ELSE '在庫あり'
END AS 在庫状況
FROM products
ORDER BY stock;
SELECT
c.customer_name AS 顧客名,
COALESCE(SUM(o.total_amount), 0) AS 総購入額,
CASE
WHEN SUM(o.total_amount) >= 100000 THEN 'VIP'
WHEN SUM(o.total_amount) >= 50000 THEN '優良'
ELSE '一般'
END AS 顧客ランク
FROM customers c
LEFT JOIN orders o ON c.customer_id = o.customer_id
GROUP BY c.customer_id, c.customer_name
ORDER BY 総購入額 DESC NULLS LAST;
SELECT
order_id AS 注文ID,
order_date AS 注文日,
CASE
WHEN strftime('%m', order_date) IN ('12', '01', '02') THEN '冬'
WHEN strftime('%m', order_date) IN ('03', '04', '05') THEN '春'
WHEN strftime('%m', order_date) IN ('06', '07', '08') THEN '夏'
ELSE '秋'
END AS 季節
FROM orders
ORDER BY order_date DESC
LIMIT 10;
解説:
INを使って複数の値をまとめて判定
strftime('%m', ...)で月を抽出
問題 6応用
条件付きカウント
カテゴリごとに、高価格商品(1000円以上)と低価格商品(1000円未満)の数を表示してください。
※横にスクロールできます
SELECT
category AS カテゴリ,
COUNT(*) AS 総商品数,
SUM(CASE WHEN price >= 1000 THEN 1 ELSE 0 END) AS 高価格商品数,
SUM(CASE WHEN price < 1000 THEN 1 ELSE 0 END) AS 低価格商品数
FROM products
GROUP BY category
ORDER BY 総商品数 DESC;
解説:
SUM + CASE で条件付きカウント
THEN 1 ELSE 0 で条件に合う行を数える
問題 7応用
平日・週末の売上
月ごとに、平日の売上と週末の売上を別々に集計してください。
※横にスクロールできます
SELECT
strftime('%Y-%m', order_date) AS 年月,
SUM(CASE
WHEN strftime('%w', order_date) NOT IN ('0', '6')
THEN total_amount ELSE 0
END) AS 平日売上,
SUM(CASE
WHEN strftime('%w', order_date) IN ('0', '6')
THEN total_amount ELSE 0
END) AS 週末売上,
SUM(total_amount) AS 総売上
FROM orders
GROUP BY strftime('%Y-%m', order_date)
ORDER BY 年月 DESC
LIMIT 6;
解説:
strftime('%w', ...)で曜日番号(0=日曜、6=土曜)
NOT IN ('0', '6') で平日を判定
問題 8チャレンジ
月別売上のピボット
1月から6月までの月次売上を、列に展開して表示してください。
※横にスクロールできます
SELECT
strftime('%Y', order_date) AS 年,
SUM(CASE WHEN strftime('%m', order_date) = '01' THEN total_amount ELSE 0 END) AS 一月,
SUM(CASE WHEN strftime('%m', order_date) = '02' THEN total_amount ELSE 0 END) AS 二月,
SUM(CASE WHEN strftime('%m', order_date) = '03' THEN total_amount ELSE 0 END) AS 三月,
SUM(CASE WHEN strftime('%m', order_date) = '04' THEN total_amount ELSE 0 END) AS 四月,
SUM(CASE WHEN strftime('%m', order_date) = '05' THEN total_amount ELSE 0 END) AS 五月,
SUM(CASE WHEN strftime('%m', order_date) = '06' THEN total_amount ELSE 0 END) AS 六月
FROM orders
GROUP BY strftime('%Y', order_date)
ORDER BY 年;
SELECT
product_name AS 商品名,
price AS 価格,
stock AS 在庫,
CASE
WHEN stock = 0 THEN '緊急'
WHEN stock <= 5 AND price >= 1000 THEN '高'
WHEN stock < 10 THEN '中'
ELSE '低'
END AS 優先度
FROM products
ORDER BY
CASE
WHEN stock = 0 THEN 1
WHEN stock <= 5 AND price >= 1000 THEN 2
WHEN stock < 10 THEN 3
ELSE 4
END,
product_name;
WITH monthly_sales AS (
SELECT
strftime('%Y-%m', order_date) AS 年月,
SUM(total_amount) AS 実績
FROM orders
GROUP BY strftime('%Y-%m', order_date)
)
SELECT
年月,
実績,
1500000 AS 目標,
ROUND(実績 * 100.0 / 1500000, 1) AS 達成率,
CASE
WHEN 実績 >= 1500000 THEN '達成'
WHEN 実績 >= 1350000 THEN '惜しい'
WHEN 実績 >= 1200000 THEN '要努力'
ELSE '未達'
END AS 評価
FROM monthly_sales
ORDER BY 年月 DESC
LIMIT 6;
解説:
CTEで月次売上を事前に計算
達成率と評価を同時に計算
📝 Step 12 のまとめ
✅ 学んだこと
CASE式:SQLの条件分岐(if文に相当)
検索CASE式:自由な条件式が書ける(範囲判定など)
単純CASE式:値の変換に便利(= での比較のみ)
ピボット変換:行を列に展開(SUM + CASE)
条件付き集計:特定条件だけをカウント・合計
ORDER BY での使用:動的な並び替え
📌 CASE式の基本形
※横にスクロールできます
-- 検索CASE式(一般的)
CASE
WHEN 条件1 THEN 結果1
WHEN 条件2 THEN 結果2
ELSE デフォルト
END
-- 単純CASE式(値の変換)
CASE 列名
WHEN 値1 THEN 結果1
WHEN 値2 THEN 結果2
ELSE デフォルト
END
-- ピボット変換
SUM(CASE WHEN 条件 THEN 値 ELSE 0 END) AS 列名
-- 条件付きカウント
SUM(CASE WHEN 条件 THEN 1 ELSE 0 END) AS 件数