Oracleで条件をわけるには通常、WHERE句を使用するが、
「DECODE」や「CASE」を使えば、SELECT句の中で条件を分けることが可能だ。
本記事では「CASE」を使ってSELECT句の中で条件を分ける方法を紹介する。
CASEは2種類の使い方がある
まず前提として、
CASEには使い方が2種類存在する。
①「値で判定するCASE」と②「式で判定するCASE」の2種類だ。
両者の使い方を順に解説していく。
① 値で判定するCASEの使い方
値で判定する「CASE」は、一番シンプルなパターンだ。
--CASEで条件をわけてSELECTする
SELECT
CASE 列名
WHEN 値1 THEN 結果1
WHEN 値2 THEN 結果2
ELSE 結果3
END
FROM table1;
指定した列名の値が
- 値1だった場合 →結果1を返す
- 値2だった場合 →結果2を返す
- それ以外の場合 →結果3を返す
という具合に、値の内容によって異なる結果を返すことができる。
値で判定するCASEのサンプル
以下は、ランキング(ranking)の値に対応して、
CASEを使用して表示する内容を変えるケースである。
--CASEで条件をわけてSELECTする
SELECT
name AS 氏名,
CASE ranking
WHEN 1 THEN '金賞'
WHEN 2 THEN '銀賞'
ELSE 'それ以外'
END AS 表彰結果
FROM table1;
--実行結果 +------+------+ | 氏名 | 表彰内容 | +------+------+ | 太郎 | 金賞 | | 次郎 | 銀賞 | | 三郎 | それ以外| | 四郎 | それ以外| | 五郎 | それ以外| +------+------+
② 式で判定するCASEの使い方
式で判定するCASEの方が最もよく使用する「CASE」の使い方だ。
「条件式」を使う事ができるため、値で判定する時と比べて幅が広がる使い方が可能となる。
--CASEで条件をわけてSELECTする
SELECT
CASE
WHEN 条件1 THEN 結果1
WHEN 条件2 THEN 結果2
ELSE 結果3
END
FROM table1;
まず値の時と異なり、CASEの後に列名を指定しない。
そして、
- 条件1を満たす場合 →結果1を返す
- 条件2を満たす場合 →結果2を返す
- それ以外の場合 →結果3を返す
という具合に、条件の内容によって異なる結果を返すことができる。
式で判定するCASEのサンプル①
以下は、ランキング(ranking)の条件に対応して、
CASEを使用して表示する内容を変えるケースである。
--CASEで条件をわけてSELECTする SELECT name AS 氏名, CASE WHEN ranking = 1 THEN '金賞' WHEN ranking = 2 THEN '銀賞' ELSE 'それ以外' END AS 表彰結果 FROM table1;
--実行結果 +------+------+ | 氏名 | 表彰内容 | +------+------+ | 太郎 | 金賞 | | 次郎 | 銀賞 | | 三郎 | それ以外| | 四郎 | それ以外| | 五郎 | それ以外| +------+------+
「式」を使うと上記のように値ではなく、
評価式の結果によってSELECT結果を変化させることが可能になる。
式で判定するCASEのサンプル② –大小比較するパターン–
「式」を使った「CASE」では大小比較も可能だ。
--CASEで90点以上→A,70点以上→B,以外→CをSELECT
SELECT
name AS 氏名,
score AS スコア,
CASE
WHEN score >= 90 THEN 'A'
WHEN score < 90 AND score >= 70 THEN 'B'
ELSE 'C'
END AS スコアランク
FROM student;
--実行結果 +------+------+------------+ | 氏名 | スコア | スコアランク | +------+------+------------+ | 太郎 | 90 | A | | 次郎 | 70 | B | | 三郎 | 70 | B | | 四郎 | 50 | C | | 五郎 | 30 | C | +------+------+------------+
上記ではスコアが90点以上、70点以上、70点未満の3種類を「CASE」で振り分け、
表示するスコアランクを変化させた。
式で判定するCASEのサンプル③ –ワイルドカード–
「式」を使った「CASE」ではワイルドカードも使用可能だ。
--CASEでワイルドカードを使ってSELECT
SELECT
name, AS 氏名
CASE
WHEN name like '太%' THEN '◯'
WHEN name like '四%' THEN '□'
ELSE null
END AS 記号
FROM student;
--実行結果
+------+------+
| 氏名 | 記号 |
+------+------+
| 太郎 | ◯ |
| 次郎 | null |
| 三郎 | null |
| 四郎 | □ |
| 五郎 | null |
+------+------+
上記では名前の先頭の文字 + %(ワイルドカード)を使って、
表示する記号を変化させた。
式で判定するCASEのサンプル④ –集計–
最後に「CASE」で条件分岐して集計するパターンを紹介する。
--CASEで男女の数をSELECT
SELECT
SUM(CASE WHEN gender = '男' THEN 1 ELSE 0 END) 男計,
SUM(CASE WHEN gender = '女' THEN 1 ELSE 0 END) 女計
FROM student;
--実行結果
+------+------+
| 男計 | 女計 |
+------+------+
| 3 | 2 |
+------+------+
男子・女子の人数をそれぞれ一度に集計している。
男なら1、女なら1を返し、1をSUMして集計しているという流れだ。
where句でわけると複数のSQLに分かれて煩雑だが、CASEを使えば上記のように一発で集計結果を表示することができる。
CASEのまとめ
- CASEには使い方が2種類存在する(「値で判定するCASE」と「式で判定するCASE」)。
- 式で判定するCASEでは、大小比較、ワイルドカード、集計などを用いてより柔軟に条件分岐が可能である。
関連記事
https://www.shift-the-oracle.com/sql/case-when-expression.html
https://docs.oracle.com/cd/E53142_01/server.761/es_eql/src/ceql_expr_case.html
上記のように値だけで条件分岐するなら、DECODE関数と機能的には全く変わらない。