Voorbereiding op programmeerinterviews · Les

Join fan-out en rijvermenigvuldiging

Waarom een join meer rijen kan opleveren dan een van beide tabellen en hoe interviewers dit testen

Les 3 van 413 stappen

Join fan-out en rijvermenigvuldiging is een gratis Voorbereiding op programmeerinterviews-les op CoddyKit. Dit is les 3 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.

Wanneer een koppeling te veel rijen oplevert

Een van de meest onthullende interviewvragen klinkt onschuldig: "kan een koppeling meer rijen opleveren dan de grootste tabel?" Het antwoord is ja. Dit verschijnsel heet fan-out of rijvermenigvuldiging.

Kandidaten die zeggen "een koppeling combineert gewoon tabellen" missen dit. Kandidaten die het exacte aantal rijen kunnen voorspellen, worden aangenomen. Deze les ontwikkelt die voorspellingsvaardigheid.

De oorzaak: één-op-veel-overeenkomsten

Fan-out ontstaat wanneer één rij aan de linkerkant overeenkomt met veel rijen aan de rechterkant. Elke overeenkomst levert een afzonderlijke uitvoerrij op.

Bij customers en orders heeft Ada (één klant) twee bestellingen. De koppeling levert één rij per bestelling op, dus Ada komt twee keer voor. De klantvelden worden herhaald; alleen de ordervelden verschillen.

SELECT c.name, o.amount
FROM customers c
JOIN orders o ON o.customer_id = c.id;
-- Ada appears twice (she has 2 orders)
-- name | amount
-- Ada  | 50
-- Ada  | 20
-- Bob  | 99

Het aantal uitvoerrijen tellen

Het aantal uitvoerrijen is gelijk aan de som van de overeenkomsten per rij aan de linkerkant, niet aan het aantal klanten.

  • Ada -> 2 bestellingen -> 2 rijen
  • Bob -> 1 bestelling -> 1 rij
  • Cleo -> 0 bestellingen -> 0 rijen (verwijderd door INNER JOIN)

Totaal = 3 rijen, ook al heeft customers eveneens 3 rijen. Verander Ada naar 10 bestellingen en het resultaat springt naar 11 rijen.

Veel-op-veel explodeert

Fan-out wordt sterker wanneer beide kanten meerdere overeenkomsten voor dezelfde sleutel hebben. Als sleutel K 3 keer aan de linkerkant en 4 keer aan de rechterkant voorkomt, levert de koppeling voor die sleutel 3 x 4 = 12 rijen op.

Zo kan een ogenschijnlijk kleine koppeling uitgroeien tot miljoenen rijen. Interviewers geven graag dubbele sleutels aan beide kanten om te zien of je de vermenigvuldiging opmerkt.

-- left has 3 rows with tag 'A', right has 4 rows with tag 'A'
SELECT l.id, r.id
FROM left_t l
JOIN right_t r ON r.tag = l.tag;
-- tag 'A' alone yields 3 * 4 = 12 output rows

De aggregatievalkuil

Dit is de fout die interviewers het vaakst inbouwen. Je koppelt orders aan order_items om itemdetails op te halen en telt daarna het orderbedrag op met SUM. Omdat elke bestelling wordt vermenigvuldigd naar meerdere itemrijen, wordt het orderbedrag één keer per item geteld.

De SUM is nu enorm opgeblazen. De query ziet er correct uit en wordt zelfs uitgevoerd, en juist dat maakt deze fout gevaarlijk.

-- BUG: order.amount duplicated across items
SELECT SUM(o.amount) AS total
FROM orders o
JOIN order_items i ON i.order_id = o.id;
-- a 3-item order counts o.amount 3 times

De opblazing in beeld

Stel dat één bestelling een bedrag van 100 en drie orderregels heeft. De koppeling levert drie rijen op, elk met bedrag 100. SUM(o.amount) retourneert 300, niet 100.

De oplossing is aggregeren op de juiste granulariteit: tel de items op, of tel afzonderlijke bestellingen afzonderlijk op. Gebruik nooit SUM voor een waarde uit een bovenliggende tabel over een gekoppelde onderliggende tabel die fan-out veroorzaakt.

o.id | o.amount | i.id
7    | 100      | 71
7    | 100      | 72
7    | 100      | 73
-- SUM(o.amount) = 300  (WRONG, should be 100)

Oplossing 1: aggregeer de onderliggende tabel eerst

De eenvoudigste oplossing is om de veel-kant vooraf te aggregeren in een subquery of CTE, zodat elke bovenliggende rij precies met één samengevatte rij overeenkomt. Geen fan-out en geen opblazing.

Hier brengen we de items terug tot één rij per bestelling voordat we de koppeling maken, zodat het bedrag van de bovenliggende rij nooit wordt gedupliceerd.

SELECT o.id, o.amount, i.item_count
FROM orders o
JOIN (
  SELECT order_id, COUNT(*) AS item_count
  FROM order_items
  GROUP BY order_id
) i ON i.order_id = o.id;

Oplossing 2: COUNT(DISTINCT) en voorwaardelijke sommen

Als je na een koppeling met fan-out moet aggregeren, tel of som dan op de juiste granulariteit. Gebruik COUNT(DISTINCT o.id) om bestellingen te tellen in plaats van itemrijen.

Let op: SUM(DISTINCT o.amount) is GEEN veilige oplossing, omdat twee verschillende bestellingen legitiem hetzelfde bedrag kunnen hebben en dan samengevoegd zouden worden. Vooraf aggregeren is betrouwbaarder.

SELECT COUNT(DISTINCT o.id)   AS num_orders,
       COUNT(i.id)            AS num_items
FROM orders o
JOIN order_items i ON i.order_id = o.id;

Fan-out detecteren voordat het problemen geeft

Een snelle diagnose waar interviewers van houden: controleer of de koppelingssleutel uniek is aan de kant die volgens jou de "één" is. Als het aantal unieke sleutels kleiner is dan het aantal rijen, bevat die kant dubbele waarden en veroorzaakt deze fan-out.

-- if this returns rows, order_id is NOT unique in order_items
SELECT order_id, COUNT(*) AS n
FROM order_items
GROUP BY order_id
HAVING COUNT(*) > 1;

Je granulariteit controleren met een telling

Controleer de plausibiliteit van het aantal rijen voordat je een aggregatie over een gekoppeld resultaat vertrouwt. Een snelle methode is het aantal gekoppelde rijen te vergelijken met het aantal rijen in de tabel waarvan je verwacht dat die de granulariteit bepaalt.

Als COUNT(*) over de koppeling groter is dan COUNT(*) van orders, heeft de koppeling fan-out veroorzaakt en loopt elke aggregatie per bestelling risico. Deze controle van één regel heeft al veel antwoorden in interviews gered.

-- joined rows should equal order count if no fan-out
SELECT COUNT(*) AS joined_rows
FROM orders o
JOIN order_items i ON i.order_id = o.id;

SELECT COUNT(*) AS order_rows FROM orders;
-- joined_rows > order_rows  =>  fan-out present

Fan-out is niet altijd een bug

Soms wil je één rij per onderliggende rij. Elke orderregel met de kopgegevens van de bestelling tonen is dan correcte fan-out. De vaardigheid bestaat uit het kennen van je gewenste granulariteit: hoeveel rijen moet één entiteit opleveren?

Geef de granulariteit aan voordat je de query schrijft. "Ik wil één rij per orderregel" tegenover "één rij per bestelling" bepaalt of fan-out een functionaliteit of een bug is.

Korte controle

Voorspel de uitvoer van een één-op-veel-koppeling.

Samenvatting: fan-out en rijvermenigvuldiging

Onthoud:

  • Een koppeling levert één rij per overeenkomend paar, dus één-op-veel-overeenkomsten dupliceren de kant met "één".
  • Veel-op-veel-sleutels vermenigvuldigen: 3 x 4 = 12 rijen voor die sleutel.
  • Een waarde uit een bovenliggende tabel aggregeren over een koppeling met fan-out blaast sommen en tellingen op.
  • Los dit op door de onderliggende tabel vooraf te aggregeren, of door op de juiste granulariteit te tellen of op te tellen, bijvoorbeeld met COUNT(DISTINCT).
  • Geef altijd eerst de beoogde granulariteit aan; fan-out is alleen een bug als deze daarmee in strijd is.
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 “Join fan-out en rijvermenigvuldiging” gratis?

Ja — de volledige tekst van “Join fan-out en rijvermenigvuldiging” 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 “Join fan-out en rijvermenigvuldiging”?

Waarom een join meer rijen kan opleveren dan een van beide tabellen en hoe interviewers dit testen 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 3 van 4.

Hoe lang duurt de les “Join fan-out en rijvermenigvuldiging”?

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. Hoe INNER JOIN rijen koppelt
  2. ON versus WHERE bij joins
  3. Join fan-out en rijvermenigvuldiging
  4. Drie of meer tabellen koppelen
← Terug naar Voorbereiding op programmeerinterviews