Voorbereiding op SQL-sollicitatiegesprekken · Les

ROW_NUMBER voor unieke nummering

Een deterministisch rijnummer toewijzen binnen elke partitie

Les 2 van 413 stappen

ROW_NUMBER voor unieke nummering is een gratis Voorbereiding op SQL-sollicitatiegesprekken-les op CoddyKit. Dit is les 2 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 SQL-sollicitatiegesprekken. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Voorbereiding op SQL-sollicitatiegesprekken bevat in totaal 4 lessen.

Wat ROW_NUMBER garandeert

ROW_NUMBER() wijst aan elke rij binnen zijn partitie een uniek geheel getal zonder gaten toe, beginnend bij 1 en volgens de ORDER BY van het window. Geen twee rijen krijgen ooit hetzelfde nummer, zelfs niet wanneer hun ordeningswaarden gelijk zijn.

Juist daarom gebruiken interviewers deze functie voor problemen waarbij je "één rij per groep selecteert" en voor het ontdubbelen van gegevens. De andere rangschikkingsfuncties (RANK, DENSE_RANK) garanderen bij gelijke waarden geen unieke nummers.

Minimale ROW_NUMBER-query

De eenvoudigste vorm nummert een volledige resultaatverzameling in een gekozen volgorde. ROW_NUMBER heeft altijd een ORDER BY binnen OVER nodig — zonder deze zou de nummering willekeurig zijn en wijzen de meeste database-engines dit af of geven ze een waarschuwing.

Hier is de werknemer die het meest recent in dienst is gekomen rijnummer 1 als je op aflopende indiensttredingsdatum sorteert.

SELECT
  name,
  hire_date,
  ROW_NUMBER() OVER (ORDER BY hire_date DESC) AS rn
FROM employees;

Nummeren binnen partities

Voeg PARTITION BY toe om rijen binnen elke groep onafhankelijk te nummeren. De teller wordt bij elke nieuwe partitiewaarde teruggezet op 1.

In het voorbeeld krijgt elke afdeling een eigen reeks 1, 2, 3, geordend op salaris. De best verdienende werknemer in elke afdeling krijgt nummer 1 — de basis van het patroon voor de N hoogste per groep.

SELECT
  department,
  name,
  salary,
  ROW_NUMBER() OVER (
    PARTITION BY department
    ORDER BY salary DESC
  ) AS dept_rn
FROM employees;

ROW_NUMBER en gelijke waarden: geen gelijke nummers

Belangrijk punt voor sollicitatiegesprekken: wanneer twee rijen dezelfde ordeningswaarden hebben, geeft ROW_NUMBER ze toch verschillende nummers. Welke rij het lagere nummer krijgt, is niet-deterministisch tenzij je een kolom als tie-breaker toevoegt.

  • RANK zou gelijke rijen dezelfde rang geven.
  • ROW_NUMBER kiest willekeurig een volgorde tussen deze rijen.

Voeg altijd een unieke tie-breaker toe aan ORDER BY om reproduceerbare resultaten te krijgen.

SELECT
  name,
  salary,
  ROW_NUMBER() OVER (
    ORDER BY salary DESC, employee_id  -- employee_id breaks ties deterministically
  ) AS rn
FROM employees;

De regel voor een deterministische tie-breaker

Als je ORDER BY geen strikte ordening oplevert (geen enkele combinatie van kolommen is uniek), kan de rijnummering tussen uitvoeringen veranderen, zelfs bij dezelfde gegevens. Interviewers verwerken deze valkuil in vragen over paginering en "het recentste record".

Vuistregel: voeg een primaire sleutel of een andere unieke kolom toe als laatste sorteersleutel wanneer het resultaat stabiel moet zijn.

-- Unstable: many rows can share the same created_at
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at DESC)

-- Stable: id guarantees a single deterministic winner
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at DESC, id DESC)

Uitgewerkt voorbeeld: recentste bestelling per klant

Een veelvoorkomende vraag: "Geef de recentste bestelling van elke klant terug." Nummer de bestellingen per klant op aflopende datum en behoud daarna rn = 1 in een buitenste query.

Omdat ROW_NUMBER precies één rij met nummer 1 per partitie garandeert, krijg je precies één rij per klant — geen dubbele rijen, zelfs niet als twee bestellingen dezelfde tijdstempel hebben. De tie-breaker lost dat op.

SELECT customer_id, order_id, order_date, amount
FROM (
  SELECT
    customer_id, order_id, order_date, amount,
    ROW_NUMBER() OVER (
      PARTITION BY customer_id
      ORDER BY order_date DESC, order_id DESC
    ) AS rn
  FROM orders
) t
WHERE rn = 1;

Uitgewerkt voorbeeld: rijen ontdubbelen

ROW_NUMBER is het duidelijkste hulpmiddel om gegevens te ontdubbelen. Partitioneer op de kolommen die een dubbele rij definiëren, sorteer volgens een voorkeursregel en behoud daarna rn = 1.

Hier beschouwen we rijen met hetzelfde e-mailadres als duplicaten en behouden we de rij die het eerst is aangemaakt. Alles met rn > 1 is een duplicaat dat je kunt verwijderen of negeren.

SELECT id, email, created_at
FROM (
  SELECT
    id, email, created_at,
    ROW_NUMBER() OVER (
      PARTITION BY email
      ORDER BY created_at ASC, id ASC
    ) AS rn
  FROM users
) t
WHERE rn = 1;

ROW_NUMBER voor paginering

Voordat OFFSET/FETCH overal beschikbaar was, werd paginering uitgevoerd met ROW_NUMBER; dat gebeurt nog steeds in SQL Server en in veel ETL-taken. Nummer de rijen in een stabiele volgorde en filter daarna in een buitenste query op een genummerd bereik.

Let op tijdens sollicitatiegesprekken: paginering is alleen correct als de ordening deterministisch is — anders kan dezelfde rij op twee pagina's verschijnen of helemaal worden overgeslagen.

SELECT *
FROM (
  SELECT *, ROW_NUMBER() OVER (ORDER BY created_at, id) AS rn
  FROM articles
) t
WHERE rn BETWEEN 21 AND 40;  -- page 2, 20 per page

Een reeks toewijzen om gegevens opnieuw te ordenen

Soms heb je alleen een opeenvolgende index nodig, bijvoorbeeld om rijen na een sortering opnieuw te nummeren, een label van 1..N te maken of rijen te koppelen aan een gegenereerde reeks. ROW_NUMBER over de gewenste ordening levert een aaneengesloten reeks zonder gaten op.

Zo geef je ook een willekeurig ongeordende verzameling een vaste positie om deze later te kunnen koppelen.

SELECT
  ROW_NUMBER() OVER (ORDER BY score DESC, player_id) AS leaderboard_position,
  player_id,
  score
FROM scores;

ROW_NUMBER versus COUNT voor de 'N-de rij'

Als je wordt gevraagd om "de op twee na recentste bestelling" of "de tweede rij", gebruik je ROW_NUMBER en filter je in een buitenste query op de exacte waarde. Omdat de nummering uniek is, levert rn = 3 precies één rij op.

Vergelijk dit met RANK: als je de op één na hoogste verschillende waarde wilt (bijvoorbeeld het op één na hoogste salaris, inclusief gelijke waarden), is ROW_NUMBER het verkeerde hulpmiddel — daarvoor heb je DENSE_RANK nodig, dat in de volgende les wordt behandeld.

SELECT order_id, order_date
FROM (
  SELECT order_id, order_date,
         ROW_NUMBER() OVER (ORDER BY order_date DESC, order_id DESC) AS rn
  FROM orders
) t
WHERE rn = 3;  -- exactly the 3rd most recent order

Valkuilen samengevat

Houd dit goed uit elkaar onder druk tijdens een sollicitatiegesprek:

  • ROW_NUMBER is binnen een partitie altijd uniek en zonder gaten.
  • De functie heeft een ORDER BY in OVER nodig; zonder een unieke tie-breaker zijn de resultaten bij gelijke waarden niet-deterministisch.
  • Je kunt de functie niet in WHERE filteren — plaats haar in een subquery/CTE.
  • Gebruik haar voor één rij per groep, het ontdubbelen van gegevens en paginering; gebruik DENSE_RANK wanneer gelijke waarden hetzelfde nummer moeten krijgen.

Korte controle

Hoe gaat ROW_NUMBER om met rijen die dezelfde waarde voor ORDER BY hebben?

Samenvatting: deterministisch nummeren

ROW_NUMBER is je hulpmiddel voor unieke nummering zonder gaten binnen partities. Je hebt geleerd om:

  • Volledige verzamelingen en groepen per partitie te nummeren.
  • Een unieke tie-breaker toe te voegen voor deterministische, reproduceerbare resultaten.
  • Problemen met de recentste rij per sleutel, het ontdubbelen van gegevens, paginering en de N-de rij op te lossen door rn in een buitenste query te filteren.

Vervolgens zie je hoe RANK en DENSE_RANK gelijke waarden bewust hetzelfde nummer geven — en hoe hun gedrag met gaten verschilt.

Gratis beginnen

Leer SQL 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
30
Lessen
120

Veelgestelde vragen

Is de les “ROW_NUMBER voor unieke nummering” gratis?

Ja — de volledige tekst van “ROW_NUMBER voor unieke nummering” 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 SQL-sollicitatiegesprekken wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus Voorbereiding op SQL-sollicitatiegesprekken bevat in totaal 4 lessen.

Wat leer ik in “ROW_NUMBER voor unieke nummering”?

Een deterministisch rijnummer toewijzen binnen elke partitie Je oefent met Voorbereiding op SQL-sollicitatiegesprekken 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 SQL-sollicitatiegesprekken te beginnen?

Ervaring vooraf is niet nodig. Voorbereiding op SQL-sollicitatiegesprekken 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 2 van 4.

Hoe lang duurt de les “ROW_NUMBER voor unieke nummering”?

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 SQL-sollicitatiegesprekken?

Ja. Elke les over Voorbereiding op SQL-sollicitatiegesprekken 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 SQL-sollicitatiegesprekken