Het berekenen van cumulatieve totals en lopende sommen werd traditioneel in SQL opgelost met windowfuncties (bijvoorbeeld SUM() OVER(ORDER BY ...)), maar in eerdere of vereenvoudigde versies van databasebeheersystemen zijn alleen subqueries en groeperingen beschikbaar. Historisch gezien zochten databasearchitecten naar omwegen totdat de SQL:2003-standaard met ondersteuning voor windowfuncties beschikbaar kwam.
Probleem — bij afwezigheid van windowfuncties moet voor elke rij handmatig de som van alle voorgaande waarden worden berekend, wat leidt tot O(N^2) geneste queries bij vrij grote datasets, tenzij er slimme technieken worden toegepast.
Oplossing:
Gewoonlijk worden gecorreleerde subqueries of tijdelijke tabellen met het bijwerken van waarden gebruikt:
Codevoorbeeld:
-- Cumulatieve som met gecorreleerde query 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; -- Via een tijdelijke tabel met handmatige update van waarden CREATE TEMPORARY TABLE temp_running (id INT, amount INT, running_total INT); -- Loop door de rijen met externe code (bijvoorbeeld pl/pgsql), voeg de som stap voor stap toe
Belangrijke kenmerken:
Garandeert ORDER BY in een gecorreleerde subquery gesorteerde resultaten?
Nee — subquery heeft niet noodzakelijk invloed op het resultaat zelf. De sortering van de uiteindelijke selectie wordt altijd extern gedefinieerd in de hoofdanvraag: het resultaat is alleen afhankelijk van filtering via WHERE.
Kan de berekening van de cumulatieve som parallel worden uitgevoerd met deze aanpak?
Nee — de volgorde is zeer belangrijk, vooral bij berekeningen die afhankelijk zijn van voorgaande rijen, waardoor eenvoudige paralelisering in gewone SQL onmogelijk is.
Waarom is een gecorreleerde subquery zo traag bij een groot aantal rijen?
Omdat voor elke rij opnieuw de som over een set van voorgaande rijen wordt berekend. Dit leidt tot O(N^2) bewerkingen. Bij een voorbeeld van 100.000 rijen kan dit al minuten of zelfs uren duren.
Een analist berekende de dagelijkse cumulatieve omzet op datum via een gecorreleerde subquery, terwijl in de tabel regelmatig verwijderde id's (gaten) verschenen. De uiteindelijke som had sprongetjes en was niet afhankelijk van de datum, maar van de volgorde van id.
Voordelen:
Nadelen:
Een ingenieur verplaatste de verwerking van de cumulatieve som naar een ETL-script (Python/pandas), en uploadde vervolgens de uiteindelijke waarden naar een aparte tabel, die alleen nieuwe records synchroniseerde. Uiteinden zijn altijd afgestemd op datum, de code werkt snel en met miljoenen records.
Voordelen:
Nadelen: