Warunkowa agregacja jest używana, gdy zachodzi potrzeba agregacji wartości (na przykład sumy lub liczby) wg różnych warunków w ramach jednego zapytania. Historycznie, aby osiągnąć podobne cele, programiści SQL musieli pisać wiele podzapytań lub robić połączenia i grupowanie oddzielnie dla każdej kategorii, co prowadziło do mniej czytelnego i mniej wydajnego kodu.
Problem polegał na trudności w jednoczesnym obliczaniu kilku agregatów z różnymi warunkami — każdy pojedynczy agregat zazwyczaj wymaga filtrowania, a proste zastosowanie SUM() lub COUNT() nie uwzględnia odpowiedniego warunku w obrębie funkcji agregacyjnej.
Rozwiązanie — zastosowanie konstrukcji CASE w obrębie funkcji agregacyjnej, co pozwala "dzielić" agregaty według różnych warunków w locie, bez potrzeby stosowania wielu złączeń:
Przykład kodu:
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;
Kluczowe cechy:
Czy można się obyć bez konstrukcji CASE dla warunkowej agregacji?
Niepoprawna odpowiedź — użycie WHERE w zapytaniu bezpośrednio z funkcją agregacyjną. W rzeczywistości WHERE filtruje wiersze przed agregacją, a nie wewnątrz każdej kolumny agregacyjnej.
Przykład kodu (nieprawidłowy sposób):
SELECT COUNT(*) FROM payments WHERE status = 'approved'; SELECT COUNT(*) FROM payments WHERE status = 'pending';
Te zapytania nie mogą być połączone w jeden wiersz wyniku według różnych warunków bez CASE.
Co się stanie, jeśli użyjesz NULL w wyrażeniu warunkowym?
Jeśli CASE nie zwraca wartości alternatywnej, to domyślnie będzie to NULL, a funkcja agregacyjna zignoruje NULL.
Przykład kodu:
SUM(CASE WHEN status = 'approved' THEN amount END) -- Jeśli status nie jest 'approved', to NULL, a wiersz jest ignorowany w SUM
Czy można użyć IF zamiast CASE?
W niektórych dialektach SQL (na przykład MySQL) jest to możliwe, ale taki kod staje się nieprzenośny między różnymi bazami danych. W uniwersalnych zapytaniach zawsze stosuj CASE.
Analityk próbował zliczyć sumy według każdego statusu, pisząc kilka oddzielnych podzapytań. Zewnętrzny raport stał się skomplikowany, a dodanie nowych statusów wymagało każdorazowo przepisania kodu.
Zalety:
Programista użył CASE w jednym wspólnym zapytaniu, tworząc uniwersalny raport z możliwością rozbudowy o nowe statusy poprzez prostą edycję jednego zapytania.
Zalety: