ProgrammatieBackend ontwikkelaar

Hoe conditional aggregatie te implementeren in SQL (bijvoorbeeld, sommen tellen per status in één query) en welke valkuilen er zijn?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

Conditional aggregatie wordt gebruikt wanneer waarden (zoals som of aantal) moeten worden geaggregeerd op basis van verschillende voorwaarden binnen één query. Historisch gezien moesten SQL-ontwikkelaars meerdere subquery's schrijven of joins en groeperingen afzonderlijk per categorie uitvoeren, wat leidde tot minder leesbare en minder efficiënte code.

Het probleem was de moeilijkheid om meerdere aggregaten met verschillende voorwaarden gelijktijdig te berekenen — elk afzonderlijk aggregaat vereist meestal filtering, en eenvoudige toepassingen van SUM() of COUNT() houden geen rekening met de vereiste voorwaarde binnen de aggregatiefunctie.

Oplossing — het gebruik van een CASE-constructie binnen de aggregatiefunctie, waardoor het mogelijk is om "aggregaten" op verschillende voorwaarden on-the-fly te scheiden, zonder meerdere joins:

Voorbeeldcode:

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;

Belangrijkste kenmerken:

  • Maakt aggregatie over meerdere voorwaarden tegelijk mogelijk in één query.
  • Werkt in alle SQL-dialekten (de exacte syntaxis ondersteuning kan verschillen).
  • Kan niet alleen met SUM, maar ook met COUNT, AVG en anderen worden gebruikt.

Vragen met een omweg.

Kan men zonder CASE-constructie voor conditional aggregatie?

Een onjuiste antwoord is het gebruik van WHERE in de query rechtstreeks samen met de aggregatiefunctie. In werkelijkheid filtert WHERE de rijen vóór de aggregatie, en niet binnen elke aggregaat kolom.

Voorbeeldcode (onjuiste manier):

SELECT COUNT(*) FROM payments WHERE status = 'approved'; SELECT COUNT(*) FROM payments WHERE status = 'pending';

Deze queries kunnen niet worden samengevoegd in één resultaatregel op basis van verschillende voorwaarden zonder CASE.

Wat gebeurt er als NULL in de voorwaardelijke expressie wordt gebruikt?

Als CASE geen alternatief resultaat teruggeeft, is dit standaard NULL, en de aggregatiefunctie negeert NULL.

Voorbeeldcode:

SUM(CASE WHEN status = 'approved' THEN amount END) -- Als status niet 'approved' is, dan NULL, en de rij wordt genegeerd in SUM

Kan IF in plaats van CASE worden gebruikt?

In sommige SQL-dialekten (bijvoorbeeld MySQL) is dit mogelijk, maar zo'n code wordt onoverdraagbaar tussen verschillende databases. Gebruik altijd CASE in universele queries.

Typische fouten en anti-patronen

  • Het gebruik van WHERE in plaats van geneste logica binnen CASE leidt tot de noodzaak om meerdere enkele queries uit te voeren, wat de prestaties vermindert.
  • Als men vergeet ELSE 0 in CASE in te stellen, kan men onjuiste aantallen/sommen krijgen door NULL-overslagen.
  • Het letterlijk kopiëren van CASE zonder de nodige controles leidt tot logische fouten en onjuiste berekeningen.

Voorbeeld uit de praktijk

Negatieve case

Een analist probeerde sommen per status te berekenen door verschillende afzonderlijke subquery's te schrijven. Het externe rapport werd ingewikkeld, en het toevoegen van nieuwe statussen vereiste telkens het herschrijven van de code.

Voordelen:

  • Makkelijk te implementeren voor één metriek. Nadelen:
  • Moeilijk schaalbaar, lage prestaties en herhalende code.

Positieve case

Een ontwikkelaar gebruikte CASE in één enkele query en maakte een universeel rapport met de mogelijkheid om nieuwe statussen eenvoudig toe te voegen via een eenvoudige bewerking van één query.

Voordelen:

  • Hoge leesbaarheid, eenvoud van schaalbaarheid, prestaties. Nadelen:
  • Vereist kennis van de CASE-syntaxis en de nuances in verschillende databases.