この記事ではCASE式の書き方、使い方を具体例を交えて解説します。
CASE式の構文
CASE式には単純CASE式と検索CASE式の2種類があります。それぞれ以下のように書きます。
-- 単純CASE式
CASE working_status
WHEN '1' THEN '正社員'
WHEN '2' THEN '契約社員'
WHEN '3' THEN 'アルバイト'
ELSE 'その他' END
-- 検索CASE式
CASE WHEN working_status = '1' THEN '正社員'
WHEN working_status = '2' THEN '契約社員'
WHEN working_status = '3' THEN 'アルバイト'
ELSE 'その他' END
WHEN句の後に条件を書き、THEN句の後にその条件がTRUEの場合に返す値を書きます。最後にENDを書きます。ELSE句はオプションでどの条件にも当てはまらないときにELSE句の値が返されます。ELSEを書かない場合にWHEN句のどの条件もTRUEならない場合はNULLが返されます。
またCASE式は上から順番に処理され、一番初めにTRUEになったWHEN句に対応するTHEN句の値を返し、そのあとのWHEN句は評価されないです。
どちらもやっていることは、working_statusというカラムが’1’の場合は’正社員’、’2’の場合は’契約社員’、’3’の場合は’アルバイト’、それ以外の場合は’その他’という文字列を返すということをしています。つまりラベルの読み替えをしています。
単純CASE式の方が検索CASE式に比べて簡潔に書くことが出来ますが、単純CASE式は条件が「=」だけという制約があります。検索CASE式は条件の部分に「>=」や「in」など様々な条件を使うことが出来ます。
一番初めにTRUEになった値が返される例
一番初めにTRUEになった値が返されるとはどういうことか実際のデータを使って見てみます。
-- テーブル作成
create table employee(
empno int,
working_status char(1)
)
-- データ挿入
insert into employee values
(1, '1'), -- '1':正社員
(2, '2'), -- '2':契約社員
(3, '3'); -- '3':アルバイト
この時に下記のsqlを実行してみます。
select empno,
case when working_status in ('1', '2', '3')
then '正社員、契約社員またはアルバイト' -- working_statusが'1'or'2'or'3'の場合(必ずTRUEになる)
when working_status = '1' then '正社員' -- working_statusが'1'の場合
when working_status = '2' then '契約社員' -- working_statusが'2'の場合
when working_status = '3' then 'アルバイト' -- working_statusが'3'の場合
else null
end 雇用形態
from employee;
雇用形態がすべて’正社員、契約社員またはアルバイト’になっています。なぜなら、CASE式は上から処理され、一番初めにTRUEになった条件のTHEN句の値が返されるからです。今回の場合はworking_statusは必ず’1’、’2’または’3’であるので、最初の条件がTRUEになり、雇用形態がすべて’正社員、契約社員またはアルバイト’になっています。
CASE式で階級分けする
PostgreSQLのサンプルデータベースのテーブルを使って、階級分けをしてみます。データベースを用意する方法は[PostgreSQL] サンプルのデータベースを用意するを参照してください。
例として使うpaymentテーブルには客のidと1回お会計の支払金額などが入っています。ここでは客の支払合計額で階級分けして、店への貢献度階級(お金を使う度合い)を作成してみます。
select customer_id,
case when sum(amount) < 50 then 1 -- 50$未満なら貢献度1
when sum(amount) < 100 then 2 -- 50$以上100$未満なら貢献度2
when sum(amount) < 150 then 3 -- 100$以上150$未満なら貢献度3
else 4 -- 150$以上なら貢献度4
end 店への貢献度
from payment group by customer_id order by cumstomer_id;
結果の一部抜粋です。支払金額の合計を店への貢献度と読み替えて貢献度階級を作成することが出来ました。
集約関数の中でCASE式を使う
集約関数の中でCASE式を使って見ます。ここでもPostgreSQLのサンプルデータベースのpaymentテーブルを使います。スタッフ1とスタッフ2の処理したそれぞれの金額の合計1行で表示してみます。
select
sum(case when staff_id = 1 then amount else 0 end) スタッフ1の合計金額,
sum(case when staff_id = 2 then amount else 0 end) スタッフ2の合計金額
from payment;
SUM関数(集約関数)の中でCASE式を書き、「スタッフ1の合計金額」を計算するときはstaff_idが1の場合はamountを返して、そうではないときは0を返すことでスタッフ1が処理した金額だけを合計しています。「スタッフ2の合計金額」も同様です。
集約関数の中でCASE式を使うことで行を列に変換することが出来ます。