CASEで条件分岐させてDBから値を取得しようとした時に書き方がわからなくて
少し手こずったのでおさらい
ちなみに元々のクエリ文はWHERE句のみ(ANDやORを使って)で
20行以上あったのが8行にまとまりました!
CASEすごい!便利
仕様:選択項目がすべての場合は全件取得、値が選択された場合はその値だけを取得する
DB:MariaDB
###まず、CASE式とは
プログラム言語にあるif文のような条件文をSQLでも書くことができる
それがCASE式です。
CASE式とはの説明がわかりやすい記事、参考にしたのはここ→https://qiita.com/sfp_waterwalker/items/acc7f95f6ab5aa5412f3
####WHERE句でCASEを使う
いろんなところにCASE式が書けるみたいですが私はWHERE句に書きました!
構文
CASE
WHEN [条件] THEN [条件を満たしたら表示する内容]
ELSE [条件を満たしていなかったら表示する内容]
END
SELECT * FROM table
WHERE
CASE WHEN :value1<>'全て' THEN :value1=value1 ELSE 1=1 END
AND
CASE WHEN :value2<>'全て' THEN :value2=value2 ELSE 1=1 END
AND
CASE WHEN :date IS NOT NULL THEN STR_TO_DATE(date, '%Y%m%d') >= STR_TO_DATE(:date, '%Y%m%d') ELSE 1=1 END
AND
CASE WHEN :enddate IS NOT NULL THEN STR_TO_DATE(enddate, '%Y%m%d') >= STR_TO_DATE(:enddate, '%Y%m%d') ELSE 1=1 END"
条件をいくつも書きたい場合、ANDを使って書ける
※ELSE 1=1 は全件取得
####書き方でわからなかったところ
CASE
WHEN [条件] THEN [条件を満たしたら表示する内容]
ELSE [条件を満たしていなかったら表示する内容]
END
CASEの構文はわかったがつなげて何個も条件分岐を書きたかったので、最初は CASE〜ENDの中に全部条件を書いてしまった
失敗例1
CASE
WHEN :value1<>'全て' THEN :value1=value1
WHEN :value2<>'全て' THEN :value2=value2
WHEN :date IS NOT NULL THEN STR_TO_DATE(date, '%Y%m%d') >= STR_TO_DATE(:date, '%Y%m%d')
WHEN :enddate IS NOT NULL THEN STR_TO_DATE(enddate, '%Y%m%d') >= STR_TO_DATE(:enddate, '%Y%m%d')
ELSE 1=1
END
この状態だと、どれか条件にマッチした場合他の条件文を通らなくなってしまった
失敗例2
CASE
WHEN :value1<>'全て' THEN :value1=value1 ELSE 1=1
WHEN :value2<>'全て' THEN :value2=value2 ELSE 1=1
WHEN :date IS NOT NULL THEN STR_TO_DATE(date, '%Y%m%d') >= STR_TO_DATE(:date, '%Y%m%d') ELSE 1=1
WHEN :enddate IS NOT NULL THEN STR_TO_DATE(enddate, '%Y%m%d') >= STR_TO_DATE(:enddate, '%Y%m%d') ELSE 1=1
END
1行ずつWHEN [条件] THEN [条件を満たしたら表示する内容]ELSE [条件を満たしていなかったら表示する内容]
で書いてみたが構文エラー、下記のようにCASE〜ENDで囲われていないからかな?と思い‥
CASE
WHEN [条件] THEN [条件を満たしたら表示する内容]
ELSE [条件を満たしていなかったら表示する内容]
END
####私的な解釈、考え方
CASE ~ END は if文でゆう if(){ }←ブロック(波括弧)に置き換えるとわかりやすい!
CASE WHEN :value1<>'全て' THEN :value1=value1 ELSE 1=1 END
↑この一文は↓のイメージ(※このif文はあくまでイメージです。)
if(value1<>'全て'){
:value1=value1
}else{
1=1
}