Die Berechnung kumulativer Summen und laufender Beträge wurde traditionell in SQL über Fensterfunktionen (zum Beispiel SUM() OVER(ORDER BY ...)) gelöst. In früheren oder vereinfachten Versionen von DBMS sind jedoch nur Unterabfragen und Gruppierungen verfügbar. Historisch haben DB-Architekten nach Alternativen gesucht, bevor der SQL:2003-Standard mit Unterstützung für Fensterfunktionen eingeführt wurde.
Problem — In Abwesenheit von Fensterfunktionen muss für jede Zeile die Summe aller vorherigen Werte explizit berechnet werden, was zu O(N^2) verschachtelten Abfragen bei ausreichend großen Auswahlmengen führt, es sei denn, es werden Tricks angewendet.
Lösung:
Üblicherweise werden korrelierte Unterabfragen oder temporäre Tabellen mit Aktualisierung der Werte verwendet:
Codebeispiel:
-- Kumulative Summe mit korrelierter Abfrage SELECT t1.id, t1.amount, ( SELECT SUM(t2.amount) FROM transactions t2 WHERE t2.id <= t1.id ) AS running_total FROM transactions t1 ORDER BY t1.id; -- Über eine temporäre Tabelle mit manueller Aktualisierung des Wertes CREATE TEMPORARY TABLE temp_running (id INT, amount INT, running_total INT); -- Durchlaufen der Zeilen mit Hilfe externen Codes (zum Beispiel pl/pgsql), während die Summen nacheinander hinzugefügt werden
Wichtige Merkmale:
Gewährleistet das ORDER BY in einer korrelierten Unterabfrage eine garantierte Sortierung?
Nein — die Subabfrage beeinflusst nicht unbedingt das Ergebnis. Die Sortierung der Endauswahl wird immer extern in der Hauptabfrage festgelegt: das Ergebnis hängt nur von der Filterung durch WHERE ab.
Kann die Berechnung der kumulativen Summe in diesem Ansatz parallelisiert werden?
Nein — die Reihenfolge ist sehr wichtig, insbesondere bei Berechnungen, die von vorhergehenden Zeilen abhängen, weshalb eine einfache Parallelisierung in gewöhnlichem SQL nicht möglich ist.
Warum ist eine korrelierte Unterabfrage bei einer großen Anzahl von Zeilen so langsam?
Weil für jede Zeile erneut die Summe über die Menge der vorhergehenden Zeilen berechnet wird. Dies führt zu O(N^2) Operationen. Bei einem Beispiel mit 100.000 Zeilen kann dies bereits Minuten oder sogar Stunden in Anspruch nehmen.
Ein Analyst berechnete den täglichen kumulativen Umsatz nach Datum über eine korrelierte Unterabfrage, während in der Tabelle zeitweise gelöschte ids (Lücken) auftauchten. Die Endsumme hatte sprunghafte Einbrüche und hing nicht vom Datum, sondern von der Reihenfolge der ids ab.
Vorteile:
Nachteile:
Ein Ingenieur übertrug die Verarbeitung der kumulativen Summe in ein ETL-Skript (Python/pandas), und lud die Endwerte in eine separate Tabelle, wobei nur neue Einträge synchronisiert wurden. Die Ergebnisse sind immer nach Datum abgestimmt, der Code läuft schnell und mit Millionen von Datensätzen.
Vorteile:
Nachteile: