条件付き集約は、レポーティングにおいて古典的な課題です。当初は、異なる指標をカウントするためにフィルター付きの個別クエリが作成されていました。すぐに、集約関数内でのCASEを使用した条件付き集約というよりコンパクトな解決策が登場しました(例:SUM(CASE WHEN ...))。フィルター、グループ化、集計ヘッダーを組み合わせる際に問題が発生する可能性があります:誤った合計値や結果の誤解釈が容易に起こり得ます。
解決策:集約関数内で条件付き集約を使用することです。たとえば、すべての従業員について「処理中」と「完了」を示す注文数を出力する必要があります:
SELECT employee_id, SUM(CASE WHEN status = 'processing' THEN 1 ELSE 0 END) as processing_count, SUM(CASE WHEN status = 'done' THEN 1 ELSE 0 END) as done_count FROM Orders GROUP BY employee_id;
重要な特徴:
CASE条件がNULLを返すとどうなりますか?
集約関数SUMはNULLを無視します。したがって、CASE WHEN ... THEN 1 ENDを記述すると、欠落した行は考慮されません。常に明示的にELSE 0を指定する方が良いでしょう。
SUM(CASE WHEN status = 'processing' THEN 1 ELSE 0 END)
条件付き集約においてWHEREフィルターがステータスの合計に影響することがありますか?
はい:主要なWHEREがサンプルを制限する場合(例:WHERE region = 'west')、計算はフィルタリングされたデータに対してのみ行われます。全体の合計のためには、サブクエリを使用するか、フィルターを削除してください。
HAVINGを使用してグループ化前の行をフィルタリングできますか?
いいえ。HAVINGは集約されたデータに対してフィルタリングを行います。元の行のフィルタリングはWHEREを介して行います。
分析レポートで使用しました:
SUM(CASE WHEN status = 'approved' THEN 1 END)
多くのNULLがあり、最終的な合計は過小評価されました。WHEREフィルターのために必要な行が失われました。
利点:
欠点:
使用したのは:
SUM(CASE WHEN status = 'approved' THEN 1 ELSE 0 END)
コードは単一のクエリに保たれ、最終的なフィルタはHAVINGによって行われました。
利点:
欠点: