Um Aggregationen mit schichtweiser Filterung (zum Beispiel: zuerst filtern, dann Summen nach Gruppen berechnen, dann über den gesamten Satz) effektiv zu erstellen, verwendet man Fensterfunktionen (OVER()) und geschachtelte GROUP BY.
Beispiel: Finden wir die maximale Bestellsumme für jeden Manager, aber nur unter den Bestellungen mit dem Status 'paid', und geben dann den Namen des Managers mit dem absoluten Maximum unter allen aus.
WITH PaidOrders AS ( SELECT ManagerID, SUM(OrderAmount) AS TotalPaid FROM Orders WHERE Status = 'paid' GROUP BY ManagerID ), WithMax AS ( SELECT *, MAX(TotalPaid) OVER() AS MaxTotalPaid FROM PaidOrders ) SELECT ManagerID, TotalPaid FROM WithMax WHERE TotalPaid = MaxTotalPaid;
Dieser Ansatz (CTE + Fensterfunktionen) ermöglicht es, mehrschichtige Filterung und Aggregation zu implementieren.
Fangfrage: "Was ist der Unterschied zwischen der Ausführung des WHERE-Filters vor der Gruppierung (GROUP BY) und der Anwendung von HAVING danach? Wie äußert sich das häufig in Berichten?"
Antwort: WHERE verwirft Zeilen bereits vor der Gruppierung, d.h. es gibt einen strengen Eingabedatenbereich. HAVING filtert aggregierte Gruppen – daher kann es vorübergehend "überflüssige" Zeilen belassen, wenn der Filter logisch nicht konsistent ist. Der falsche Standort des Filters führt häufig zu Fehlern in den endgültigen Aggregaten oder zu falschen Berichtsergebnissen.
-- Wir erhalten die Summe nur für 'paid', durch WHERE SELECT ManagerID, SUM(OrderAmount) FROM Orders WHERE Status = 'paid' GROUP BY ManagerID; -- Oder wir berechnen Summen für alle und schneiden dann mit HAVING SELECT ManagerID, SUM(OrderAmount) FROM Orders GROUP BY ManagerID HAVING SUM(OrderAmount) > 1000;
Geschichte
Projekt: Verkaufsberichte, Prüfungsaudit.
Fehler: Der Entwickler verwendete HAVING Status='paid' anstelle von WHERE, wodurch die Aggregationen fälschlicherweise auch unbezahlte Bestellungen einbezogen, was zu fehlerhaften jährlichen KPI-Berechnungen für das Personal führte.
Geschichte
Projekt: Bankanalyse.
Fehler: Bei der komplexen Aggregation wurde versucht, eine Fensterfunktion ohne PARTITION BY anzuwenden, wodurch die Aggregationen auf der gesamten Tabelle statt auf der Gruppe berechnet wurden. Das Budget der Abteilung wurde inkorrekt berechnet – es musste manuell wiederhergestellt werden.
Geschichte
Projekt: Online-Shop, Bestellstatistiken.
Fehler: Bei der Optimierung wurde die Einbettung von Fensterfunktionen in die Unterabfrage nicht berücksichtigt – wodurch der Server die Daten mehrfach verarbeitete, was zu einer 20-fachen Verlangsamung der Anfrage im Vergleich zu einem einfachen doppelten GROUP BY führte.