ProgrammatieBackend ontwikkelaar

Hoe cumulerende (aaneengeschakelde) totals in SQL te berekenen zonder windowfuncties, met inachtneming van de prestaties bij duizenden of miljoenen rijen?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord

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:

  • De methode werkt alleen als er een unieke sorteernorm is (id, datum van productie)
  • Gecorreleerde subquery's schalen slecht — exponentiële toename van de uitvoeringstijd
  • Voor grote hoeveelheden gegevens is het logischer om ETL te gebruiken met aggregatie buiten SQL of met procedurele middelen

Vragen met een haakje.

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.

Typische fouten en anti-patronen

  • Onjuiste filtering op id in plaats van de werkelijke datum — sommen "springen" op gaten in id
  • Poging om te sommen zonder de gegevens te sorteren
  • Dit soort aanpak gebruiken voor enorme tabellen, wanneer ETL of partitionering nodig is

Voorbeeld uit het leven

Negatief geval

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:

  • Werkt voor kleine datasets, geen windowfuncties vereist

Nadelen:

  • Gegevens zijn onjuist, berekening is niet zoals verwacht
  • Moeilijke ondersteuning

Positief geval

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:

  • Betrouwbaarheid, mogelijkheid voor herberekeningen zonder stilstandtijd
  • Ondersteuning voor grote volumes

Nadelen:

  • Complexer landschap — externe verwerkingsinstrumenten zijn nodig