条件付き集約は、1つのクエリ内でさまざまな条件に基づいて値(合計やカウントなど)を集約する必要がある場合に使用されます。歴史的に、SQL開発者はこのような目的を達成するために複数のサブクエリを書く必要があり、各カテゴリごとに結合や集約を別々に行う必要があるため、可読性が低く、パフォーマンスが劣るコードにつながっていました。
問題は、異なる条件で複数の集約を同時に計算することが難しいということです。各集約は通常フィルタリングを必要とし、単純に SUM() または COUNT() を適用しても、集約関数内の必要な条件を考慮しません。
解決策は、集約関数内に CASE 構文を使用し、異なる条件に基づいて集約を「分割」することで、複数の結合を行うことなく実現できるようにします。
コードの例:
SELECT department, SUM(CASE WHEN status = 'approved' THEN amount ELSE 0 END) AS approved_sum, SUM(CASE WHEN status = 'pending' THEN amount ELSE 0 END) AS pending_sum, COUNT(CASE WHEN status = 'rejected' THEN 1 END) AS rejected_count FROM payments GROUP BY department;
重要な特徴:
CASE構文なしで条件付き集約を実現できますか?
不正確な回答は、集約関数と直接WHEREをクエリで使用することです。実際、WHEREは集約前に行をフィルタリングし、各集約列内でフィルタリングしません。
コードの例(不正な方法):
SELECT COUNT(*) FROM payments WHERE status = 'approved'; SELECT COUNT(*) FROM payments WHERE status = 'pending';
これらのクエリは、CASEなしで異なる条件に基づいて1つの結果行に連結することはできません。
条件式内でNULLを使用するとどうなりますか?
CASEが代替値を返さない場合、デフォルトでNULLになり、集約関数はNULLを無視します。
コードの例:
SUM(CASE WHEN status = 'approved' THEN amount END) -- ステータスが 'approved' でない場合はNULLになり、行はSUMで無視されます
CASEの代わりにIFを使用できますか?
一部のSQL方言(例えばMySQL)では可能ですが、そのようなコードは異なるデータベース間での移植性がなくなります。一般的なクエリでは常にCASEを使用してください。
アナリストは各ステータスごとの合計を計算しようとし、複数の個別のサブクエリを書きました。外部レポートは複雑になり、新しいステータスを追加するたびにコードを書き換える必要がありました。
利点:
開発者は1つの共通クエリでCASEを使用し、新しいステータスのための拡張可能なユニバーサルレポートを簡単な編集で作成しました。
利点: