ProgrammatieBackend ontwikkelaar, BI analist

Hoe implementeer je betrouwbare aggregatie met unieke voorwaarden (conditional aggregation) in SQL bij het opstellen van rapporten met meerdere filters? Welke nuances bestaan er bij het combineren van HAVING, CASE en aggregatiefuncties?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

Aggregatie met voorwaarden is een klassieke taak voor rapportage. In eerste instantie werden aparte queries met filters gemaakt om verschillende indicatoren te tellen. Al snel verscheen een compactere oplossing - voorwaardelijke aggregatie met behulp van CASE binnen aggregatiefuncties (bijvoorbeeld, SUM(CASE WHEN ...)). Het probleem doet zich voor bij het combineren van filters, groeperingen en totalen: het is gemakkelijk om onjuiste totalen te krijgen of het resultaat verkeerd te interpreteren.

Oplossing: gebruik voorwaardelijke aggregatie binnen aggregatiefuncties. Bijvoorbeeld, je moet het aantal "in behandeling" en "voltooid" bestellingen per werknemer weergeven:

SELECT employee_id, SUM(CASE WHEN status = 'processing' THEN 1 ELSE 0 END) as processing_count, SUM(CASE WHEN status = 'done' THEN 1 ELSE 0 END) as done_count FROM Orders GROUP BY employee_id;

Belangrijke kenmerken:

  • Ongeacht de WHERE-filter worden alle benodigde totalen in één query berekend.
  • CASE binnen SUM maakt het mogelijk om complexe meerduidige rapporten te maken.
  • HAVING wordt toegepast op al geaggereerde gegevens, voor post-filtering van het aggregatieresultaat.

Vragen met een valstrik.

Wat gebeurt er als de CASE-omschrijving NULL in plaats van 0 retourneert?

De aggregatiefunctie SUM negeert NULL. Daarom, als je CASE WHEN ... THEN 1 END schrijft, worden de gemiste rijen niet meegerekend. Het is beter om altijd expliciet ELSE 0 in te stellen.

SUM(CASE WHEN status = 'processing' THEN 1 ELSE 0 END)

Kan een WHERE-filter de uiteindelijke som van de statussen wijzigen bij voorwaardelijke aggregatie?

Ja: als de hoofd WHERE de selectie beperkt (bijvoorbeeld, WHERE region = 'west'), dan zullen de berekeningen alleen worden uitgevoerd op de gefilterde gegevens. Voor globale totalen gebruik je een subquery of verwijder je de filter.

Kan HAVING worden gebruikt om rijen vóór groepering te filteren?

Nee. HAVING filtert al gegroepeerde gegevens op aggregaten. Filtering van de oorspronkelijke rijen gebeurt via WHERE.

Typische fouten en anti-patterns

  • Ontbrekende ELSE, CASE retourneert NULL, onjuiste totalen.
  • Combineren van WHERE en HAVING, waardoor verkeerde rijen worden verkregen.
  • Meerdere queries gebruiken in plaats van één met CASE.

Voorbeeld uit het leven

Negatief geval

In een analytisch rapport gebruikten we:

SUM(CASE WHEN status = 'approved' THEN 1 END)

Er waren veel NULL's, de uiteindelijke totalen waren verlaagd. Door de WHERE-filter gingen sommige benodigde rijen verloren.

Voordelen:

  • Korte code.

Nadelen:

  • Onjuiste resultaten, rapport verkeerd uitgelegd aan het bedrijf.

Positief geval

We gebruikten:

SUM(CASE WHEN status = 'approved' THEN 1 ELSE 0 END)

De code werd onderhouden in één enkele query, filters op het totaal - via HAVING.

Voordelen:

  • Correcte, transparante indicatoren.
  • Makkelijk om een nieuwe status toe te voegen.

Nadelen:

  • Queries worden langer, voorzichtigheid betreft de filters is vereist.