【SQL】 COUNT関数をSELECT句のCASE式条件分岐で使ったらハマった話
関数まみれの重たいエクセルでのデータ分析して消耗している皆様こんばんわ!!!
金山雄星です。
今日はRedashのダッシュボード作成でSQLを書いていたときに少しハマってしまった時の話。
SELECT pref_name,
SUM(CASE WHEN sex='1' THEN population ELSE 0 END)AS cnt_m,
SUM(CASE WHEN sex='2' THEN population ELSE 0 END)AS cnt_f
FROM PopTbl2
GROUP BY pref_name;
上のコードのようにSELECT句でCASE式を使って、条件分岐して集計しようとしてました。
(ちなみに上記のコードは、愛読書「達人に学ぶSQL徹底指南書」より引用。)
もちろんアフィリエイトリンクなんで、気になった方は検索などせずに下のバナーから飛んでくださいね!笑
普段、SUM関数で行うときは上のコードの丸パクリで上手くいってたのですが、今回、COUNT関数を使うと沼にハマりました。
❌間違ったコード
SELECT ym,
COUNT(CASE WHEN sex='1' THEN id ELSE 0 END)AS cnt_m,
COUNT(CASE WHEN sex='2' THEN id ELSE 0 END)AS cnt_f
FROM orders
GROUP BY ym;
いつものSUMでやってた要領でCOUNTすると
実行エラーにはならいものの数字が合わない、、
⭕️正解のコード
SELECT ym,
COUNT(CASE WHEN sex='1' THEN id ELSE NULL END)AS cnt_m,
COUNT(CASE WHEN sex='2' THEN id ELSE NULL END)AS cnt_f
FROM orders
GROUP BY ym;
どこを変えたか分かりました??
ELSE 0 → ELSE NULLと修正したんです。
理由を説明すると
CASE式のやっていることはラベルの読み替えでしかないので、
イメージとしてはWHENの条件にヒットしなかったカラムは、ELSE 0なら0に書き替えられて集計計算されている。
SUMの場合は0を足した値が正になるが、
COUNTの場合は0になったレコードも数えられてしまって、CASE式の条件分岐が機能していないように見えていたという訳。
ELSE NULLとすることで解決。
結論
・CASE式のやっていることはラベルの読み替えでしかない
・集約関数をSELECT句でCASE式を用いた条件分岐で使うときは
SUMの時は ELSE 0
COUNTの時は ”ELSE NULL”
で上手くいく!
BIツールが入ってるとドライブがCSVまみれにならなくて最高ですね。
役に立ったという方はいいねよろしくお願いします!
Twitterも見ていってくださいね!
https://twitter.com/YuseiKanayama
金山雄星
P.S.
noteでSQLのソースコードをもうちょっとキレイに書く方法はないでしょうか、、