SQLで条件分岐するには、CASE式を使用します。
CASE式を使用することで、プログラム言語と似たようにSQLでも条件分岐を記述することができます。
Tipsでは、DB2 for IBMiのデータベースで、CASE式による様々な条件分岐方法をご紹介します。
CASE式とは?
SQLの中で条件分岐が記述できればと思ったことはないでしょうか。
CASE式を利用すると、プログラムを作成するように条件分岐を記述することが可能です。
CASE式は「条件」により出力する「結果」を変えたい場合に使用します。
また、CASE式には、単純CASE式、検索CASE式があり少し記述が異なります。
さらに、CASE式は、SELECT文節だけでなく、WHERE文節やUPDATE文節でも使用可能です。
今回のTipsでは、SQLの記述例を踏まえながらご紹介いたします。
なお、CASE式については以下、IBMのサイトもご確認ください。
■CASE式
https://www.ibm.com/docs/ja/i/7.3?topic=expressions-case-expression
単純CASE式と検索CASE式
SAMPLEライブラリに以下のような顧客ファイル(CUSTOMER)が存在する場合を例とします。
CUSTCD(顧客CD) | CUNAME(顧客名) | CUGEND(性別) | CUAGE(年齢) | CURANK(ランク) | CUPONT(ポイント) |
C0001 | 山田 太郎 | 0 | 50 | C4 | 8000 |
C0002 | 山田 花子 | 1 | 44 | C1 | 3000 |
C0003 | 三我路 春男 | 0 | 25 | C2 | 6000 |
C0004 | 三我路 夏子 | 1 | 15 | C3 | 5000 |
単純CASE式の例
単純CASE式はわかり易い記述が可能です。しかし、実現できることが限定的です。
単純CASE式は特定フィールドの値が一致した場合に、出力する式を変化させる際に使用します。
例えば、性別コード(CUGEND)の値によって出力する結果の文字を変えたい場合には以下のように記述します。
SELECT CUNAME,
CASE CUGEND
WHEN '0' THEN '男性'
WHEN '1' THEN '女性'
ELSE '不明'
END AS "GENDER"
FROM SAMPLE.CUSTOMER
CASEの後に条件となるフィールド名(条件)を記述して、WHENでCASE後に設定されたフィールド名の値によって条件分岐します。
THEN 以降に記述された式が結果として出力されます。
例では、文字列で「男性、女性、不明」のいずれかを出力することになります。
ELSEは条件に設定された値が’0’でも’1’でもない場合に出力されます。
また、CASE式ではELSEの条件を省略可能です。
結果
CUNAME(顧客名) | GENDER(性別) |
山田 太郎 | 男性 |
山田 花子 | 女性 |
三我路 春男 | 男性 |
三我路 夏子 | 女性 |
検索CASE式の例
実際にSQLで条件分岐を記述する場合、単純な一致だけでなく条件式により判別することが多いと思います。条件式を使用する場合には検索CASE式を使用します。
例えば、年齢(CUAGE)の値によって、各年代の結果を出力する場合には以下のように記述します。
SELECT CUNAME,
CASE WHEN CUAGE < 20 THEN '20才未満'
WHEN CUAGE < 40 THEN '20代~30代'
WHEN CUAGE < 60 THEN '40代~50代'
ELSE '60代以降'
END AS "GENERATION"
FROM SAMPLE.CUSTOMER
条件式にすることで、単純な一致だけでなく、条件指定して条件分岐が可能となります。
また、CASE式では上部の条件に一致した段階で、条件の処理は打ち切られて下部の条件は考慮されません。そのため、CUAGEが15であった場合、「CUAGE < 40」や「CUAGE < 60」も条件に一致しますが、上部に記述された、CUAGE < 20の条件に一致した段階で条件分岐処理が終了します。
結果
CUNAME(顧客名) | GENERATION(世代) |
山田 太郎 | 40代~50代 |
山田 花子 | 40代~50代 |
三我路 春男 | 20代~30代 |
三我路 夏子 | 20才未満 |
SELECT文節のCASE式 その他の使い方
CASE式と集計関数
CASE式は集計関数と組み合わせて使用することも可能です。
例えば、SAMPLE.CUSTOMERファイルから年齢が20才以上となる人数をカウントする場合に、CASE式を使うのであれば、以下のような記述となります。
SELECT SUM(
CASE
WHEN CUAGE >= 20 THEN 1
ELSE 0
END) AS "OVER20"
FROM SAMPLE.CUSTOMER
結果
OVER20(20才以上) |
3 |
もちろん、本例のような、20才以上の人数を取得する際、CASE式を使わなくても取得することができますが、集計関数内でCASE式が利用できることを認識ください。
条件の連結
検索CASE式で複数のフィールドを条件に記述したい場合、AND や ORで連結した条件を作成することも可能です。
例えば、「20才以上」かつ「ポイントを5000以上」保持しているユーザー名には、結果フィールドのフラグに1を設定する場合、ANDで条件を連結することで表現することができます。
SELECT CUNAME,
CASE
WHEN CUAGE >= 20 AND CUPONT >= 5000 THEN '1'
ELSE '0'
END AS "OVER20_POINT5000"
FROM SAMPLE.CUSTOMER
結果
CUNAME(顧客名) | OVER20_POINT5000(20以上5000ポイント以上保持) |
山田 太郎 | 1 |
山田 花子 | 0 |
三我路 春男 | 1 |
三我路 夏子 | 0 |
複数条件の記述(INの使用)
複数の条件を指定する場合、IN述部を使用することも可能です。
例えば、会員のランクが「C3,C4,C5」の場合は「プレミア会員」、「C1,C2」の場合は「一般会員」と出力する場合には以下となります。
SELECT CUNAME,
CASE
WHEN CURANK IN ('C3', 'C4', 'C5') THEN 'プレミア会員'
WHEN CURANK IN ('C1', 'C2') THEN '一般会員'
END AS "KUBUN"
FROM SAMPLE.CUSTOMER
結果
CUNAME(顧客名) | KUBUN(区分) |
山田 太郎 | プレミア会員 |
山田 花子 | 一般会員 |
三我路 春男 | 一般会員 |
三我路 夏子 | プレミア会員 |
■IN述部
https://www.ibm.com/docs/ja/i/7.3?topic=predicates-in-predicate
CASE文の入れ子
CASE式は入れ子にすることも可能です。
条件分岐(CASE式)の中に更なる条件分岐(CASE式)を記述することができます。
以下では、「プレミア会員」かつ ポイントを5001以上保有している場合、5000以下の場合、「一般会員」かつ ポイントを5001以上保有している場合、5000以下の場合を条件分岐で表現しています。
SELECT CUNAME,
CASE
WHEN CURANK IN ('C3', 'C4', 'C5') THEN
CASE WHEN CUPONT > 5000 THEN 'プレミア会員ポイント5001以上'
ELSE 'プレミア会員ポイント5000以下'
END
WHEN CURANK IN ('C1', 'C2') THEN
CASE WHEN CUPONT > 5000 THEN '一般会員ポイント5001以上'
ELSE '一般会員ポイント5000以下'
END
END AS "KUBUN"
FROM SAMPLE.CUSTOMER
結果
CUNAME(顧客名) | KUBUN(区分) |
山田 太郎 | プレミア会員ポイント5001以上 |
山田 花子 | 一般会員ポイント5000以下 |
三我路 春男 | 一般会員ポイント5001以上 |
三我路 夏子 | プレミア会員ポイント5000以下 |
条件指定(Where文節)での使用例
条件指定(Where文節)中にCASE式を使用することも可能です。
Where文節にCASE式を使用することで複雑な検索結果を取得することができます。
以下例ではWhere文節でCASE式を利用して、「ポイントが5000以上」、「顧客名が’三’から始まり」 かつ 「会員ランクがC2」と「ポイントが5000以下」の顧客名一覧を出力します。
SELECT CUNAME
FROM SAMPLE.CUSTOMER
WHERE 1 = (
CASE WHEN CUPONT >= 5000 THEN (
CASE WHEN CUNAME LIKE '三%' AND CURANK = 'C2' THEN 1
ELSE 0
END)
ELSE 1
END)
※CASE式の結果で1を返却して、同じ1と比較することで、一致条件に含めています。
結果
CUNAME(顧客名) |
山田 花子 |
三我路 春男 |
上記のSQLの場合は、通常のWHERE文節でも記述することができます。
CASE式を利用すると、ELSE(条件以外)の分岐ができるため直感的にわかり易く記述できる場合もあると思います。
CASE式を利用しない場合の例
SELECT CUNAME
FROM SAMPLE.CUSTOMER
WHERE ((CUPONT >= 5000
AND (CUNAME LIKE '三%'
AND CURANK = 'C2'))
OR CUPONT < 5000)
更新時のCASE式使用例
CASE式はUPDATE文節にも使用することができます。
以下では 「会員ランクが C5」の場合は、現在保有ポイントの15%をポイントに追加
「会員ランクがC4」の場合は、保有ポイントの10%をポイントに追加 、 「会員ランクがC3」の場合は保有ポイントの5%をポイントに追加するSQLです。
UPDATE SAMPLE.CUSTOMER
SET CUPONT = CUPONT +
CASE
WHEN CURANK = 'C5' THEN INT(CUPONT * 0.15)
WHEN CURANK = 'C4' THEN INT(CUPONT * 0.10)
WHEN CURANK = 'C3' THEN INT(CUPONT * 0.05)
ELSE 0
END
UPDATEの実行後、SQLにて各ユーザーのポイントを確認すると以下になります。
SELECT CUNAME ,CURANK ,CUPONT FROM SAMPLE.CUSTOMER
UPDATE前
CUNAME(顧客名) | CURANK(ランク) | CUPONT(ポイント) |
山田 太郎 | C4 | 8000 |
山田 花子 | C1 | 3000 |
三我路 春男 | C2 | 6000 |
三我路 夏子 | C3 | 5000 |
UPDATE後
CUNAME(顧客名) | CURANK(ランク) | CUPONT(ポイント) |
山田 太郎 | C4 | 8800 |
山田 花子 | C1 | 3000 |
三我路 春男 | C2 | 6000 |
三我路 夏子 | C3 | 5250 |
おわりに
今回のTipsでは、CASE式についてご紹介しました。
Valenceのデータソース作成時等、SQLを入力して定義する際、CASE式を使用するとSQL内で条件分岐で結果を返すことが可能になりますので是非ご活用ください。