Voorbereiding op programmeerinterviews · Les

Filteren op een windowresultaat

Waarom u een windowfunctie in een subquery of CTE moet verpakken om erop te kunnen filteren

Les 4 van 413 stappen

Filteren op een windowresultaat is een gratis Voorbereiding op programmeerinterviews-les op CoddyKit. Dit is les 4 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Voorbereiding op programmeerinterviews. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Voorbereiding op programmeerinterviews bevat in totaal 4 lessen.

Waarom je in WHERE niet op een venster kunt filteren

Een veelvoorkomende verrassing in sollicitatiegesprekken: WHERE ROW_NUMBER() OVER (...) = 1 schrijven veroorzaakt een fout. Vensterfuncties zijn niet toegestaan in WHERE, GROUP BY of HAVING.

De reden is de logische uitvoeringsvolgorde. WHERE wordt uitgevoerd om rijen te selecteren voordat vensterfuncties worden berekend. Het venster is dan nog niet eens berekend, dus je kunt er niet naar verwijzen in een filter.

De uitleg van de uitvoeringsvolgorde

Vensterfuncties worden berekend in een speciale fase die na FROM, WHERE, GROUP BY en HAVING komt, maar vóór de uiteindelijke ORDER BY en LIMIT.

Op het moment dat WHERE wordt uitgevoerd, bestaat de rang of het rijnummer dus nog niet. Om daarop te filteren, moet je eerst het venster laten voltooien en daarna de gegenereerde kolom filteren in een buitenste querylaag.

Het patroon met een subquery als omhulling

De standaardoplossing: bereken de vensterfunctie in een binnenste query (een afgeleide tabel), geef het resultaat een alias en filter vervolgens op die alias in de buitenste WHERE.

De afgeleide tabel moet een alias hebben (t hier) — interviewers letten erop als kandidaten die vergeten. rn is nu een gewone kolom die de buitenste query kan vergelijken.

SELECT *
FROM (
  SELECT
    name, department, salary,
    ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS rn
  FROM employees
) t
WHERE rn = 1;

Het CTE-patroon (vaak overzichtelijker)

Een Common Table Expression doet hetzelfde, maar met een beter leesbare structuur. Definieer de rangschikking in een WITH-stap en filter deze daarna in de hoofdquery.

Functioneel identiek aan de subquery, maar interviewers geven bij live coderen meestal de voorkeur aan CTE's omdat de bedoeling van boven naar beneden duidelijk wordt.

WITH ranked AS (
  SELECT
    name, department, salary,
    ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS rn
  FROM employees
)
SELECT name, department, salary
FROM ranked
WHERE rn = 1;

Uitgewerkt voorbeeld: top N per groep

Het meest voorkomende vensterprobleem: "de 3 best betaalde medewerkers per afdeling". Rangschik binnen de CTE en behoud daarna buiten de CTE rn <= 3.

Kies de rangschikkingsfunctie op basis van de gewenste verwerking van gelijke standen: ROW_NUMBER beperkt het resultaat tot precies 3 rijen per afdeling; schakel over op RANK/DENSE_RANK als gelijke standen op de grens moeten worden meegenomen.

WITH ranked AS (
  SELECT department, name, salary,
         ROW_NUMBER() OVER (
           PARTITION BY department ORDER BY salary DESC
         ) AS rn
  FROM employees
)
SELECT department, name, salary
FROM ranked
WHERE rn <= 3
ORDER BY department, rn;

Uitgewerkt voorbeeld: filteren op een voortschrijdend totaal

Het patroon met een omhulling is niet alleen voor rangen. Elk vensterresultaat — voortschrijdende totalen, voortschrijdende gemiddelden, verschillen met LAG — moet op dezelfde manier worden gefilterd.

Hier berekenen we een voortschrijdend saldo en behouden we alleen de rijen waarin dit voor het eerst boven 1000 uitkomt. Het filter staat buiten de vensterlaag.

WITH balances AS (
  SELECT
    account_id, txn_date, amount,
    SUM(amount) OVER (
      PARTITION BY account_id ORDER BY txn_date
    ) AS running_balance
  FROM transactions
)
SELECT *
FROM balances
WHERE running_balance > 1000;

QUALIFY: de snelkoppeling in sommige databases

Snowflake, BigQuery, Teradata en DuckDB bieden een QUALIFY-clausule waarmee je vensterresultaten rechtstreeks filtert — een omhulling is niet nodig. Deze wordt na de vensterfuncties uitgevoerd, precies op de plek die je nodig hebt.

Noem QUALIFY om je brede kennis te laten zien, maar vermeld erbij dat dit geen onderdeel is van de SQL-standaard en ontbreekt in PostgreSQL, MySQL en SQL Server. Daar heb je nog steeds de subquery/CTE nodig.

-- Snowflake / BigQuery only:
SELECT department, name, salary
FROM employees
QUALIFY ROW_NUMBER() OVER (
  PARTITION BY department ORDER BY salary DESC
) = 1;

Verwar HAVING niet met filteren op vensters

Kandidaten proberen soms HAVING om een rang te filteren. HAVING filtert groepen na de aggregatie met GROUP BY en wordt nog steeds vóór de vensterfuncties uitgevoerd. Daarom kan het ook niet naar een vensterkolom verwijzen.

  • WHERE → filtert rijen vóór het groeperen en vóór de vensters.
  • HAVING → filtert geaggregeerde groepen, nog steeds vóór de vensters.
  • Een venster filteren → vereist een buitenste query (of QUALIFY).

Een voorfilter combineren met een vensterfilter

Vaak filter je zowel vóór als na het venster. Pas gewone rijfilters toe in de binnenste WHERE (zodat het venster alleen relevante rijen ziet) en filter daarna het vensterresultaat in de buitenste query.

In dit voorbeeld beperken we ons eerst tot actieve medewerkers en kiezen we daarna de best verdienende medewerker per afdeling uit die groep. Als je WHERE active binnen de query plaatst, verandert dat welke rijen worden gerangschikt.

WITH ranked AS (
  SELECT department, name, salary,
         ROW_NUMBER() OVER (
           PARTITION BY department ORDER BY salary DESC
         ) AS rn
  FROM employees
  WHERE is_active = true        -- pre-filter before ranking
)
SELECT * FROM ranked
WHERE rn = 1;                   -- post-filter on the window

Opmerking over prestaties

Interviewers kunnen vragen of de omhulling de prestaties verslechtert. Meestal niet: de optimaliseerder behandelt de subquery/CTE als onderdeel van één uitvoeringsplan en berekent het venster één keer. Alleen doordat je de query hebt omhuld, ontstaat er geen extra scan.

Eén kanttekening: in sommige engines kan een CTE een optimalisatiebarrière zijn (en in het geheugen worden opgeslagen), waardoor een afgeleide tabel of QUALIFY voor veelgebruikte paden een beter plan kan opleveren. Gebruik EXPLAIN om dit te meten als het relevant is.

Veelgemaakte fouten

Laatste controlelijst:

  • Zet nooit een vensterfunctie in WHERE/HAVING — dat veroorzaakt een fout.
  • Geef de afgeleide tabel altijd een alias; een naamloze subquery in FROM wordt afgewezen.
  • Kies de rangschikkingsfunctie op basis van de gewenste verwerking van gelijke standen.
  • Gebruik QUALIFY alleen waar dit wordt ondersteund; gebruik anders de CTE/subquery als omhulling.

Korte controle

Waarom heb je een omhulling nodig om een vensterfunctie te filteren?

Samenvatting: vensterresultaten filteren

Je hebt de cirkel rond gemaakt voor rangschikkingsfuncties in vensters:

  • Vensterfuncties worden uitgevoerd na WHERE/GROUP BY/HAVING, dus je kunt ze daar niet filteren.
  • Wikkel het venster in een subquery of CTE (altijd met alias) en filter het resultaat in de buitenste query.
  • Dit vormt de basis voor top-N-per-groep, de nieuwste rij per sleutel en drempels voor voortschrijdende totalen.
  • QUALIFY is een handige snelkoppeling die geen onderdeel is van de standaard en alleen in Snowflake/BigQuery beschikbaar is.

Je beschikt nu over de volledige gereedschapskist voor rangschikking die interviewers het vaakst toetsen.

Gratis beginnen

Leer Voorbereiding op programmeerinterviews met een AI-tutor — gratis

Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.

Cursussen
90
Lessen
360

Veelgestelde vragen

Is de les “Filteren op een windowresultaat” gratis?

Ja — de volledige tekst van “Filteren op een windowresultaat” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus Voorbereiding op programmeerinterviews wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus Voorbereiding op programmeerinterviews bevat in totaal 4 lessen.

Wat leer ik in “Filteren op een windowresultaat”?

Waarom u een windowfunctie in een subquery of CTE moet verpakken om erop te kunnen filteren Je oefent met Voorbereiding op programmeerinterviews door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.

Heb ik ervaring nodig om met Voorbereiding op programmeerinterviews te beginnen?

Ervaring vooraf is niet nodig. Voorbereiding op programmeerinterviews op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 4 van 4.

Hoe lang duurt de les “Filteren op een windowresultaat”?

De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.

Kan ik code schrijven en uitvoeren in deze les over Voorbereiding op programmeerinterviews?

Ja. Elke les over Voorbereiding op programmeerinterviews bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.

Alle lessen in deze cursus

  1. OVER, PARTITION BY en ORDER BY
  2. ROW_NUMBER voor unieke nummering
  3. RANK versus DENSE_RANK bij gelijke waarden
  4. Filteren op een windowresultaat
← Terug naar Voorbereiding op programmeerinterviews