SQL-joins en tabelrelaties

Leer hoe je in SQL gegevens uit gerelateerde tabellen combineert. Volg primaire en refererende sleutels van tabel naar tabel, schrijf inner joins en behoud rijen zonder overeenkomst met left, right en full outer joins. Koppel een tabel aan zichzelf, maak alle combinaties met een cross join en beantwoord vragen over veel-op-veelrelaties via koppeltabellen en ketens van drie of meer tabellen. Leer ten slotte dubbele rijen, te hoge totalen en weggevallen rijen herkennen en een joinresultaat controleren voordat je erop vertrouwt. De meeste voorbeelden gebruiken één kleine winkeldatabase, met kleine extra tabellen voor hiërarchieën, veel-op-veelrelaties en combinaties. Elk voorbeeld toont de daadwerkelijke resultaatrijen.

BeginnerLes 5 van 6 in SQL: de basis

Wat je leert

  1. Lees hoe tabellen door sleutels zijn gekoppeld en leg uit wat een join met hun rijen doet voordat je er een schrijft.
    • Vind de koppelingen tussen tabellen in een schema
      Gebruik primaire en refererende sleutels om te zien hoe tabellen samenhangen, benoem elke relatie als een-op-een, een-op-veel of veel-op-veel en bepaal welke kolommen een join moet vergelijken.
    • Leg uit wat een join met rijen doet
      Beschrijf een join als het koppelen van rijen die aan een voorwaarde voldoen, voorspel de breedte en lengte van het resultaat en gebruik tabelaliassen en gekwalificeerde kolomnamen.
  2. Schrijf inner joins die alleen rijen met een overeenkomst in beide tabellen retourneren, met ON, USING en bereikvoorwaarden, en filter en sorteer de gecombineerde rijen.
    • Schrijf een inner join met ON
      Koppel twee tabellen op hun sleutelkolommen met JOIN ... ON, voorspel precies welke rijen worden geretourneerd en voeg filters, sortering en duidelijke kolomnamen toe.
    • Gebruik USING, NATURAL JOIN, kommajoins en bereikvoorwaarden
      Herken andere manieren om een inner join te schrijven, leg het risico van elke manier uit en koppel rijen op een bereik in plaats van op een gelijke sleutel.
  3. Gebruik left, right en full outer joins om rijen zonder overeenkomst te behouden, ontbrekende gegevens te vinden en elke voorwaarde zo te plaatsen dat deze filtert wat je bedoelt.
    • Behoud alle rijen van één tabel met LEFT JOIN
      Schrijf een left outer join, voorspel de met NULL-waarden aangevulde rijen en gebruik de join om rijen te vinden die geen overeenkomst in een andere tabel hebben.
    • Gebruik RIGHT JOIN en FULL OUTER JOIN
      Behoud rijen zonder overeenkomst uit de rechtertabel of uit beide tabellen, herschrijf een right join als een left join en gebruik een full join om twee lijsten te vergelijken.
    • Plaats voorwaarden op de juiste manier in ON of WHERE
      Leg uit waarom een voorwaarde zich in ON anders gedraagt dan in WHERE bij een outer join en kies voor elke voorwaarde de juiste plaats.
  4. Gebruik selfjoins om rijen binnen één tabel te koppelen, gebruik cross joins om alle combinaties te maken en herken een onbedoelde cross join.
    • Koppel rijen uit dezelfde tabel met een selfjoin
      Koppel een tabel met twee aliassen aan zichzelf om verwijzingen binnen de tabel te volgen, zoals werknemers en hun leidinggevenden, en om rijen van dezelfde tabel aan elkaar te koppelen.
    • Maak alle combinaties met een cross join
      Gebruik CROSS JOIN om elke rij van één tabel aan elke rij van een andere tabel te koppelen, voorspel de omvang van het resultaat en herken onbedoelde Cartesische producten.
  5. Gebruik koppeltabellen om vragen over veel-op-veelrelaties te beantwoorden en koppel drie of meer tabellen in één query, waarbij je bij elke stap de juiste rijen behoudt.
    • Bevraag veel-op-veelrelaties via een koppeltabel
      Leg uit hoe een koppeltabel twee tabellen verbindt en gebruik joins via die tabel om vragen in beide richtingen te beantwoorden, ook over rijen zonder overeenkomst.
    • Koppel drie of meer tabellen in één query
      Plan een pad van sleutels door meerdere tabellen, schrijf één join per schakel en lees waar elke rij van een resultaat met meerdere tabellen voor staat.
    • Behoud rijen zonder overeenkomst in een joinketen
      Combineer outer en inner joins in een keten zonder rijen te verliezen die je wilde behouden, en controleer elke stap van de keten.
  6. Herken wanneer een join rijen vermenigvuldigt of verliest, verhelp te hoge aantallen en totalen en controleer een joinresultaat voordat je erop vertrouwt.
    • Verhelp dubbele rijen en te hoge totalen
      Leg uit waarom joins langs een-op-veelkoppelingen rijen herhalen en tel en sommeer waarden op het juiste niveau, zodat de totalen kloppen.
    • Controleer een joinresultaat voordat je erop vertrouwt
      Voorspel hoeveel rijen een join moet retourneren, herken de verschijnselen van veelgemaakte joinfouten en doorloop voor elke joinquery een korte checklist.

SQL-joins: uitleg

6 hoofdstukken

1

Sleutels en gecombineerde rijen

Een join begint met een relatie tussen rijen. Klantgegevens en bestelgegevens staan in aparte tabellen en sleutels vertellen je hoe je ze samenbrengt. Lees het kleine winkelschema, onderscheid een-op-een-, een-op-veel- en veel-op-veelkoppelingen en volg een pad voor een rapport. Bekijk vervolgens hoe overeenkomende paren resultaatrijen worden, waarom namen zich kunnen herhalen en hoe aliassen de herkomst van elke geselecteerde kolom duidelijk maken.

1.1 Sleutels en paden tussen tabellen

Het adres van een klant hoort bij de klant. De datum van een bestelling hoort bij de bestelling. Door deze gegevens in aparte tabellen te bewaren, verminder je herhaling, maar een rapport heeft vaak gegevens uit beide nodig. Een join combineert hun rijen binnen een query.

Lees de sleutels

Een primaire sleutel identificeert één rij. Het kan één kolom zijn of meerdere kolommen samen. Een refererende sleutel verwijst naar een primaire sleutel of een andere unieke sleutel, in een andere tabel of in dezelfde tabel. In de winkeldatabase verwijst orders.customer_id naar customers.customer_id.

customer_idnamecity
1AnaDenver
2BenAustin
3ChloeDenver
4DevBoston
order_idcustomer_idorder_datetotal
10112026-03-0222,00
10212026-03-1525,50
10322026-03-2060,00
104NULL2026-03-2115,00

Bestellingen 101 en 102 verwijzen allebei naar klant 1, Ana. Bestelling 103 verwijst naar Ben. Bestelling 104 is een bestelling als gast: de klantsleutel is NULL en verwijst dus naar geen enkele klant. Het bestelnummer identificeert de bestelling, niet de klant. Als je order_id aan customer_id koppelt, vergelijk je identificatiewaarden die niets met elkaar te maken hebben.

Benoem de relatie
RelatieBetekenisWaar de koppeling staat
Een-op-eenElke rij heeft maximaal één overeenkomst aan de andere kant.Een refererende sleutel is ook uniek, zoals bij één toegangspas per werknemer.
Een-op-veelEén ouder kan meerdere kinderen hebben; elk kind heeft maximaal één ouder.De refererende sleutel staat aan de veel-kant, zoals in orders.
Veel-op-veelRijen aan beide kanten kunnen meerdere overeenkomsten hebben.Een koppeltabel bevat een refererende sleutel naar elke kant.

De klant-bestelrelatie is een-op-veel. Een klant kan geen, één of meerdere bestellingen hebben. Dat betekent niet dat de klanttabel voor elke aankoop een bestel-ID opslaat. Elke bestelling slaat haar eigen klantverwijzing op.

Bij studenten en cursussen kan geen van beide kanten met slechts één verwijzing alle koppelingen beschrijven. Een rij in enrollments legt één student-cursuspaar vast. Meerdere inschrijvingsrijen kunnen naar dezelfde student verwijzen en meerdere naar dezelfde cursus.

Volg een route voordat je SQL schrijft

Om producten te tonen die elke klant heeft gekocht, volg je customers → orders → order_items → products. De koppelingen gebruiken achtereenvolgens customer_id, order_id en product_id. Elke koppeling heeft een eigen voorwaarde nodig. Een orderregel levert de ontbrekende verbinding tussen een bestelling en een product.

Lees wat het schema betekent en kijk niet alleen naar de spelling van kolommen. employees.manager_id kan verwijzen naar employees.emp_id, ook al verschillen de namen. Omgekeerd benoemen customers.name en products.name verschillende soorten zaken. Je moet ze niet koppelen alleen omdat beide name heten.

Een vastgelegde refererende sleutel is een nuttige aanwijzing, maar SQL kan ook tabellen koppelen zonder vastgelegde integriteitsregel. Een prijs kan overeenkomen met een prijsklasse en twee werknemers kunnen overeenkomen omdat ze dezelfde leidinggevende hebben. De voorwaarde moet de relatie uitdrukken die voor de vraag nodig is.

Belangrijkste punten

  • Een primaire sleutel identificeert een rij; een refererende sleutel verwijst naar een primaire of unieke sleutel.
  • De refererende sleutel staat aan de veel-kant van een een-op-veelrelatie.
  • Een koppeltabel legt de paren in een veel-op-veelrelatie vast.
  • Volg de koppelingen in het schema en geef elke koppeling een zinvolle voorwaarde.

1.2 Hoe overeenkomende rijen een resultaat vormen

Een join bouwt nieuwe rijen op door invoerrijen te combineren. Begin met de koppelingsregel en vraag je af hoeveel overeenkomsten elke rij heeft. Het antwoord bepaalt zowel welke rijen verschijnen als hoe vaak hun waarden worden herhaald.

Denk in paren

Stel je bij een inner join elke klant naast elke bestelling voor. Behoud een paar alleen als o.customer_id = c.customer_id waar is. Bestelling 101 wordt gekoppeld aan Ana, niet aan Ben, Chloe of Dev. Ook bestelling 102 wordt aan Ana gekoppeld. Eén klant kan dus meerdere resultaatrijen opleveren.

De voorwaarde kan waar, onwaar of onbekend zijn. Een gelijkheid met NULL is onbekend, dus gastbestelling 104 vindt geen overeenkomende klant. Een outer join behoudt ook rijen zonder overeenkomst aan de gekozen zijde en vult de kolommen van de ontbrekende tegenhanger met NULL.

Dit beeld van paren legt joins beter uit dan overlappende cirkels. Een join verzamelt niet alleen gedeelde items: hij bouwt gecombineerde rijen op en herhaalde sleutels kunnen meer uitvoerrijen opleveren dan elk van de invoertabellen bevat. Als twee rijen aan de ene kant en drie aan de andere een sleutel delen, levert die sleutel zes overeenkomende paren op.

Kies kolommen los van de overeenkomsten

De klanttabel van de winkel heeft drie kolommen en de besteltabel heeft er vier. Met JOIN ... ON retourneert SELECT * ze alle zeven, inclusief beide exemplaren van customer_id. Je kunt ook alleen de velden selecteren die het rapport nodig heeft:

SELECT c.name, o.order_id, o.total
FROM customers c
JOIN orders o ON o.customer_id = c.customer_id
ORDER BY o.order_id;

Het resultaat is (Ana; 101; 22,00), (Ana; 102; 25,50) en (Ben; 103; 60,00). De sleutelkolommen zorgen voor de koppeling zonder dat ze in de geselecteerde uitvoer hoeven te verschijnen. Minder kolommen selecteren verandert de breedte van het resultaat, niet welke invoerparen overeenkomen.

Geef tabellen korte, duidelijke namen

In FROM customers c is c een tabelalias. Verwijs naar kolommen van die tabel als c.name en c.customer_id. De expressie c.name is een gekwalificeerde kolomnaam: het deel vóór de punt geeft aan welke tabelrol de waarde levert.

Beide gekoppelde tabellen bevatten customer_id. Als je bij de vorm met ON alleen SELECT customer_id schrijft, kan de database niet kiezen tussen de twee kolommen en ontstaat een fout door een dubbelzinnige kolomverwijzing. Schrijf c.customer_id of o.customer_id, afhankelijk van de waarde die je nodig hebt. Door ook andere geselecteerde kolommen te kwalificeren, maak je hun herkomst gemakkelijk zichtbaar.

AS vóór een tabelalias is optioneel in PostgreSQL, SQLite, MySQL en SQL Server. Oracle accepteert het niet, dus FROM customers c is een bruikbare algemene vorm. Nadat je een tabel een alias hebt gegeven, gebruik je die alias consequent.

Lees de logische volgorde van de query

FROM en de bijbehorende joins bouwen de gecombineerde rijen op. WHERE filtert die rijen. SELECT kiest de uitvoerkolommen en ORDER BY sorteert het resultaat. Een filter kan een gekoppelde kolom gebruiken, ook als die kolom niet is geselecteerd. Zo kan WHERE c.city = 'Denver' een rapport filteren dat alleen namen en ordertotalen toont.

Zonder ORDER BY garandeert de database geen bepaalde rijvolgorde. Een query die vandaag Ana eerst toont, kan later een andere rij eerst tonen; sorteren is een aparte instructie naast het koppelen.

Belangrijkste punten

  • Een inner join behoudt elk paar waarvoor de voorwaarde waar is.
  • Herhaalde sleutelwaarden kunnen voor één invoerrij meerdere rijen opleveren.
  • Aliassen en gekwalificeerde namen geven aan welke tabel een kolom levert.
  • Joins bouwen rijen op voordat WHERE ze filtert en SELECT kolommen kiest.
  • Gebruik ORDER BY als de rijvolgorde van belang is.
2

Inner joins schrijven

Inner joins beantwoorden vragen waarvoor aan beide kanten overeenkomende gegevens nodig zijn, zoals een klantnaam naast een bestelling. Stel een expliciete voorwaarde op, bekijk de daadwerkelijke resultaatrijen en voeg filters en sortering toe. Lees vervolgens de verkorte en oudere vormen die je in bestaande query's kunt tegenkomen. Koppelingen op bereiken introduceren een ander soort voorwaarde, waarbij overlappende klassen of gaten kunnen veranderen hoeveel rijen elke waarde oplevert.

2.1 Rijen koppelen met JOIN en ON

Gebruik een inner join als een resultaatrij een overeenkomst in beide tabellen nodig heeft. JOIN en INNER JOIN betekenen hetzelfde. Geen van beide behoudt een rij zonder overeenkomst.

Bouw de query in drie delen op

Noem eerst de tabellen en hun rollen. Geef daarna de relatie aan in ON. Kies ten slotte de kolommen die je wilt tonen.

SELECT c.name, o.order_id, o.total
FROM customers c
JOIN orders o ON o.customer_id = c.customer_id
ORDER BY o.order_id;

Lees de voorwaarde als “de klantverwijzing van de bestelling is gelijk aan de identificatiewaarde van deze klant”. Voor bestelling 101 is de verwijzing 1, dus die wordt aan Ana gekoppeld. Bestelling 102 heeft ook verwijzing 1 en bestelling 103 heeft verwijzing 2. Het volledige resultaat is:

nameorder_idtotal
Ana10122,00
Ana10225,50
Ben10360,00

Ana verschijnt tweemaal omdat ze twee overeenkomende bestellingen heeft. Chloe en Dev hebben er geen en verschijnen dus niet. Gastbestelling 104 heeft een klantverwijzing met NULL, die aan geen enkele gelijkheid met een klantsleutel voldoet.

Filter en sorteer de gecombineerde rijen

Om alleen klanten uit Denver te tonen, plaats je WHERE c.city = 'Denver' na de join en vóór ORDER BY. Het resultaat wordt (Ana; 101; 22,00) en (Ana; 102; 25,50). Chloe woont ook in Denver, maar de inner join heeft voor haar geen rij opgeleverd.

Bij een inner join levert dit filter in ON dezelfde paren op. Een leesbare afspraak is om koppelingsvoorwaarden voor tabellen in ON en rapportfilters in WHERE te zetten. Deze gelijkwaardigheid geldt niet voor outer joins.

Je kunt sorteren op een gekoppelde kolom die niet in de geselecteerde uitvoer staat. Je kunt de joinsleutels ook uit de uitvoer weglaten: de bovenstaande query koppelt op customer_id en toont een naam, een bestelnummer en een totaal. De rol van een kolom bij het koppelen staat los van haar rol in het rapport.

Vergelijk elk deel van een sleutel

Sommige records worden door een paar kolommen geïdentificeerd. Een verzendregel die naar een orderregel verwijst, kan zowel de identificatiewaarde van de bestelling als die van het product nodig hebben:

SELECT s.order_id, s.product_id, oi.quantity
FROM shipment_lines s
JOIN order_items oi
  ON s.order_id = oi.order_id
 AND s.product_id = oi.product_id;

Beide vergelijkingen moeten waar zijn voor een overeenkomst. Als je alleen order_id vergelijkt, wordt elke verzendregel aan elke productregel in die bestelling gekoppeld. De query kan dan succesvol worden uitgevoerd en toch de verkeerde productaantallen beschrijven.

Verander de volgorde zonder de betekenis te veranderen

FROM orders o JOIN customers c ON c.customer_id = o.customer_id geeft dezelfde klant-bestelparen. Ook als je de twee kanten van = omdraait, blijft de gelijkheid behouden. SELECT * kan de kolommen na het omwisselen van tabellen anders ordenen en de rijvolgorde blijft onbepaald tenzij je sorteert.

Een veel ingrijpendere wijziging is ON o.order_id = c.customer_id. Beide kolommen bevatten getallen, dus dit is geldige SQL, maar ze identificeren verschillende dingen. In de winkelgegevens levert dit nul rijen op: bestel-ID's 101–104 zijn nooit gelijk aan klant-ID's 1–4. Controleer de relatie in het schema, ook als de database geen syntaxisfout meldt.

Belangrijkste punten

  • JOIN betekent INNER JOIN: rijen zonder overeenkomst aan beide kanten worden uitgesloten.
  • Zet de relatie in ON en voeg daarna rapportfilters en sortering toe.
  • Vergelijk alle delen van een samengestelde sleutel met AND.
  • Geldige SQL kan nog steeds de verkeerde kolommen vergelijken.

2.2 Andere manieren om een koppeling aan te geven

ON maakt een voorwaarde expliciet, maar bestaande SQL kan kortere of oudere vormen gebruiken. Lees elke vorm door je af te vragen welke paren hij behoudt. Sommige vormen veranderen ook hoe gedeelde kolommen in de uitvoer verschijnen.

USING noemt de gedeelde sleutel

Als de sleutelkolommen dezelfde naam hebben, gebruikt deze query een verkorte gelijkheid:

SELECT c.name, o.order_id
FROM customers c
JOIN orders o USING (customer_id)
ORDER BY o.order_id;

De query retourneert (Ana, 101), (Ana, 102) en (Ben, 103). USING (customer_id) betekent dat de twee kolommen customer_id worden vergeleken. Met SELECT * retourneert de query zes kolommen en toont ze de gedeelde sleutel eenmaal; JOIN ... ON bevat beide invoersleutelkolommen.

Bij een samengestelde sleutel noem je beide namen: USING (order_id, product_id). Elke genoemde kolom moet onder die naam in beide invoertabellen bestaan.

PostgreSQL, SQLite, MySQL en Oracle ondersteunen USING; SQL Server doet dat niet. In Oracle moet een kolom die in USING wordt genoemd ongekwalificeerd zijn als je ernaar verwijst. Schrijf dus SELECT customer_id, niet SELECT c.customer_id. Andere kolommen kunnen nog steeds hun tabelalias gebruiken.

NATURAL JOIN kiest kolommen voor je

Een NATURAL JOIN vergelijkt alle kolomnamen die de invoertabellen delen, combineert die gelijkheidstests met AND en toont de gedeelde kolommen eenmaal. Deze vorm wordt ondersteund door PostgreSQL, SQLite, MySQL en Oracle, maar niet door SQL Server.

Die automatische keuze kan een query ongemerkt veranderen. Klanten en bestellingen delen nu alleen customer_id. Als je een kolom city aan bestellingen toevoegt, vereist een natural join dat zowel klant-ID als plaats overeenkomt. Een bezorgplaats die verschilt van de plaats van de klant kan dan een eerder overeenkomende bestelling verwijderen.

Klanten en producten hebben allebei name, maar de ene kolom benoemt een persoon en de andere een product. Hun natural join zou die niet-gerelateerde namen vergelijken en retourneert in de winkelgegevens geen rijen. Zonder gedeelde kolomnamen retourneert een natural join daarentegen elke combinatie. Gebruik ON of een bewust gekozen USING-lijst om de koppelingsregel zichtbaar te houden.

Lees oudere kommajoins
SELECT c.name, o.order_id
FROM customers c, orders o
WHERE o.customer_id = c.customer_id;

Dit retourneert dezelfde drie paren als de inner join. De voorwaarde staat nu in WHERE. Als je die vergeet, worden alle vier klanten aan alle vier bestellingen gekoppeld, wat 16 rijen oplevert. Bij JOIN ... ON staat elke tabel naast haar eigen voorwaarde, waardoor langere query's gemakkelijker te controleren zijn.

Koppel een waarde aan een bereik

Een equijoin gebruikt gelijkheid. Een niet-equijoin gebruikt een andere vergelijking, zoals een bereiktest:

SELECT p.name, b.band
FROM products p
JOIN price_bands b
  ON p.price BETWEEN b.min_price AND b.max_price;

De klassen zijn Budget 0,00–4,99, Standard 5,00–19,99 en Premium 20,00–999,99. Mug voor 8,00 en Stapler voor 12,00 vallen in Standard; Pen voor 1,50 en Notebook voor 4,25 vallen in Budget. Premium heeft geen overeenkomend product en levert geen rij op.

BETWEEN omvat beide grenspunten. Een nieuwe klasse Gift van 8,00 tot 15,00 zou Mug en Stapler elk een tweede overeenkomst geven. Door het gat tussen 4,99 en 5,00 zou een prijs van 4,995 geen overeenkomst hebben. Bereiken bepalen het resultaat net als sleutels: een waarde kan geen, één of meerdere overeenkomsten hebben.

Belangrijkste punten

  • USING vergelijkt de genoemde kolommen met dezelfde naam en toont elke gedeelde sleutel eenmaal.
  • NATURAL JOIN hangt af van elke gedeelde kolomnaam, dus schemawijzigingen kunnen het resultaat veranderen.
  • Een kommajoin heeft zijn koppelingsvoorwaarde in WHERE nodig.
  • Een niet-equijoin kan op bereiken koppelen; overlappingen leveren extra overeenkomsten op en door gaten blijven waarden zonder overeenkomst.
  • SQL Server gebruikt ON en heeft geen syntaxis voor USING of NATURAL JOIN.
3

Rijen zonder overeenkomst behouden

Rapporten moeten ontbrekende relaties vaak zichtbaar houden: klanten zonder bestellingen, onverkochte producten of records die in een van twee lijsten ontbreken. Outer joins behouden die rijen en markeren de ontbrekende tegenhanger met NULL-waarden. Kies welke kant behouden moet blijven en volg hoe voorwaarden het resultaat veranderen als ze tijdens het koppelen of daarna worden toegepast. De plaats van één datumtest kan bepalen of een klant helemaal verdwijnt.

Een rapport dat vraagt om “alle klanten, inclusief klanten zonder bestellingen” heeft een left outer join nodig. LEFT JOIN behoudt elke linkerrij. De join koppelt elke overeenkomende rechterrij, of levert één rij met NULL-waarden als er geen overeenkomst is. Het woord OUTER is optioneel.

Volg de behouden tabel
SELECT c.name, o.order_id, o.total
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
ORDER BY c.customer_id, o.order_id;
nameorder_idtotal
Ana10122,00
Ana10225,50
Ben10360,00
ChloeNULLNULL
DevNULLNULL

Ana levert nog steeds twee rijen op. Een left join brengt de bestellingen van een klant niet terug tot één. Chloe en Dev leveren elk precies één rij op omdat geen van beiden een overeenkomst heeft. In totaal zijn er vijf rijen: drie overeenkomende paren en twee klanten zonder overeenkomst.

De join retourneert vóór latere filters minstens evenveel rijen als de linkerinvoer. Tel voor elke linkerrij de overeenkomsten; als die er geen heeft, tel je één met NULL-waarden aangevulde rij. Dit verklaart waarom vier klanten vijf rijen kunnen opleveren.

Gastbestelling 104 ontbreekt. Als je elke klant behoudt, behoud je niet ook de bestellingen zonder overeenkomst. Om elke bestelling te behouden, begin je met orders o LEFT JOIN customers c ON c.customer_id = o.customer_id. Als je vervolgens o.order_id, c.name selecteert, krijg je (101, Ana), (102, Ana), (103, Ben) en (104, NULL). Chloe en Dev verschijnen niet meer.

Vind rijen zonder tegenhanger

Een left anti-join behoudt alleen rijen waarvoor geen overeenkomst is gevonden:

SELECT c.name
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
WHERE o.order_id IS NULL;

De left join maakt eerst alle vijf rijen. WHERE behoudt daarna Chloe en Dev, van wie de bestelsleutels NULL zijn. Hun ontbrekende tegenhanger is precies waar de query naar zoekt.

Kies een kolom aan de rechterkant die bij een echte overeenkomst geen NULL kan zijn. De primaire sleutel van een bestelling is een goede test. Als je een optionele coupon_code test, behoud je ook echte overeenkomende bestellingen zonder kortingsbon. Dat zou dus niet “geen bestelling” betekenen. Gebruik IS NULL: = NULL wordt als onbekend beoordeeld en behoudt in WHERE geen rijen.

Hetzelfde patroon vindt onverkochte producten:

SELECT p.name
FROM products p
LEFT JOIN order_items oi ON oi.product_id = p.product_id
WHERE oi.order_id IS NULL;

Dit retourneert (Stapler), het enige product zonder orderregel. Een echte overeenkomende regel heeft hier noodzakelijkerwijs een bestel-ID, dus de test vindt de ontbrekende regel.

Interpreteer een ontbrekende waarde voordat je die vervangt

Een met NULL-waarden aangevulde outer-joinrij betekent dat er geen overeenkomende tegenhanger is. Een opgeslagen NULL in een echte bestelling kan daarentegen betekenen dat een veld niet is ingevuld. Dat zijn verschillende situaties, ook al verschijnen beide als NULL.

COALESCE(o.total, 0) kiest het eerste argument dat geen NULL is. Voor Chloe en Dev zou dit 0 tonen. Dat kan nuttig zijn voor een rapport over bestedingen, maar een nul in een kolom met het opschrift “ordertotaal” kan een echte bestelling met een waarde van nul suggereren. Zorg dat het opschrift en de betekenis van het rapport bij elkaar passen.

Belangrijkste punten

  • Een left join behoudt de linkerrijen en levert NULL-waarden voor ontbrekende rechtertegenhangers.
  • Tel elk overeenkomend paar, plus één rij voor elke linkerrij zonder overeenkomst.
  • Gebruik voor een anti-join WHERE right_key IS NULL op een sleutel die bij een overeenkomst geen NULL kan zijn.
  • Een rechterrij zonder overeenkomst blijft bij een left join niet behouden.
  • COALESCE kan de weergave van ontbrekende waarden veranderen; kies een opschrift dat hun betekenis duidelijk houdt.

3.2 De rechterkant of beide kanten behouden

Soms staan de benodigde rijen rechts van een join. Soms moeten beide invoertabellen behouden blijven om ontbrekende records te kunnen vergelijken. Right en full outer joins maken deze keuzes expliciet.

Herschrijf een right join als een left join
SELECT c.name, o.order_id
FROM customers c
RIGHT JOIN orders o ON o.customer_id = c.customer_id;

Dit behoudt elke bestelling: (Ana, 101), (Ana, 102), (Ben, 103) en (NULL, 104). De rechtertabel is orders, dus de gastbestelling blijft behouden. Chloe en Dev zijn linkerrijen zonder overeenkomst en blijven niet behouden.

Als je de invoertabellen omwisselt, krijg je de gelijkwaardige vorm orders o LEFT JOIN customers c ON o.customer_id = c.customer_id. Met dezelfde expliciete selectielijst krijg je dezelfde waarden. Bij SELECT * kan de standaardkolomvolgorde veranderen. Als je in een rapport overal left joins gebruikt, is de kant die behouden moet blijven vaak gemakkelijker te volgen.

Behoud ontbrekende rijen uit beide invoertabellen
SELECT c.name, o.order_id
FROM customers c
FULL OUTER JOIN orders o ON o.customer_id = c.customer_id;

Het resultaat bevat (Ana, 101), (Ana, 102), (Ben, 103), (Chloe, NULL), (Dev, NULL) en (NULL, 104). Dit zijn drie overeenkomende paren, twee klanten zonder overeenkomst en één bestelling zonder overeenkomst: zes rijen. De klantkolommen zijn NULL voor gastbestelling 104; de bestelkolommen zijn NULL voor Chloe en Dev.

JoinBehouden rijen zonder overeenkomst
LEFT JOINAlleen linkerinvoer
RIGHT JOINAlleen rechterinvoer
FULL OUTER JOINBeide invoertabellen

Een full join is nuttig voor een aansluitcontrole, zoals het controleren van een voorraadlijst van een magazijn tegen een fysieke telling. Overeenkomende sleutels verschijnen samen; sleutels die slechts aan één kant voorkomen, blijven zichtbaar. Als je in de winkelquery WHERE c.customer_id IS NULL OR o.order_id IS NULL toevoegt, blijven alleen Chloe, Dev en bestelling 104 over.

Als je twee lijsten met hetzelfde soort sleutel aansluit, kan elk van de invoersleutels in de uitvoer NULL zijn. COALESCE(w.sku, k.sku) AS sku selecteert de beschikbare SKU uit de magazijnalias w of de tellijstalias k. Met een gecombineerde sleutelkolom kan het rapport records identificeren die in een van beide lijsten ontbreken.

Controleer de ondersteuning van de syntaxis

PostgreSQL, SQL Server en Oracle ondersteunen right en full outer joins. SQLite ondersteunt beide vanaf versie 3.39.0, die in 2022 uitkwam. Oudere SQLite-versies accepteren ze niet. MySQL ondersteunt right joins, maar heeft geen FULL OUTER JOIN; een omweg combineert de resultaten van een left en een right join met UNION.

Oudere Oracle-SQL kan in plaats daarvan de optionele zijde markeren met (+) in WHERE. Zo behoudt WHERE c.customer_id = o.customer_id(+) de klanten en vult het ontbrekende bestelkolommen met NULL, net als een left join vanaf klanten. De markering hoort bij de kant die mag ontbreken. Gebruik bij het schrijven van nieuwe query's de benoemde joinvormen LEFT, RIGHT en FULL.

Belangrijkste punten

  • Een right join wordt een left join als de tabellen van plaats wisselen.
  • Rijen van een full join bestaan uit overeenkomende paren plus rijen zonder overeenkomst van beide kanten.
  • Een full join kan verschillen bij een aansluitcontrole zichtbaar maken.
  • SQLite heeft versie 3.39.0 of later nodig voor right en full joins; MySQL heeft geen trefwoord voor een full join.

3.3 Bepalen of een voorwaarde in ON of WHERE hoort

Een outer join scheidt twee beslissingen: welke paren als overeenkomsten tellen en welke voltooide resultaatrijen het rapport behoudt. ON neemt de eerste beslissing. WHERE neemt de tweede, nadat rijen zonder overeenkomst NULL-waarden hebben gekregen.

Behoud iedereen, maar beperk de overeenkomende bestellingen

Stel dat een rapport alle klanten nodig heeft en alleen hun bestellingen vanaf 10 maart:

SELECT c.name, o.order_id
FROM customers c
LEFT JOIN orders o
  ON o.customer_id = c.customer_id
 AND o.order_date >= '2026-03-10';

De datumtest maakt deel uit van het koppelen. Ana's bestelling 101 is te vroeg, maar bestelling 102 voldoet. Bens bestelling 103 voldoet ook. Chloe en Dev hebben geen tegenhanger die voldoet, dus krijgen ze elk een met NULL-waarden aangevulde rij. Het resultaat is (Ana, 102), (Ben, 103), (Chloe, NULL) en (Dev, NULL).

Filter de rijen na de join

Verplaats dezelfde datumtest naar WHERE:

SELECT c.name, o.order_id
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
WHERE o.order_date >= '2026-03-10';

Nu maakt de join eerst vijf rijen, inclusief de met NULL-waarden aangevulde rijen voor Chloe en Dev. De datumvergelijking is onbekend voor die NULL-waarden, dus WHERE verwijdert ze. Ook Ana's vroege bestelling wordt verwijderd. Alleen (Ana, 102) en (Ben, 103) blijven over.

De versie met WHERE levert dezelfde overeenkomende rijen op als een inner join met dat datumfilter.

Filter de behouden tabel bewust

Ook een voorwaarde op de linkerkant in ON kan geen linkerrijen verwijderen. Neem ON o.customer_id = c.customer_id AND c.city = 'Denver'. Ana kan met beide bestellingen overeenkomen, Chloe heeft er geen en Ben en Dev voldoen bij geen enkele mogelijke overeenkomst aan het plaatsgedeelte. Alle vier klanten blijven behouden, met NULL in de bestelkolommen voor Ben, Chloe en Dev.

Om alleen klanten uit Denver op te vragen, zet je WHERE c.city = 'Denver' na de gewone sleutelvoorwaarde. Het resultaat is (Ana, 101), (Ana, 102) en (Chloe, NULL). Chloe blijft behouden omdat het filter haar eigen woonplaats test, niet een ontbrekend bestelveld.

Wat de voorwaarde moet doenGebruikelijke plaats bij een left join
Geschikte overeenkomsten aan de rechterkant beperken en elke linkerrij behoudenON
Beperken welke linkerrijen in het rapport horenWHERE
Rijen vinden waarvan de rechtertegenhanger ontbreektWHERE met right_key IS NULL

De anti-jointest hoort na de join omdat deze het met NULL-waarden aangevulde resultaat onderzoekt. Inner joins behouden geen rijen zonder overeenkomst, dus als je een filter tussen ON en WHERE verplaatst, veranderen hun overeenkomende paren niet. Lees bij het controleren van een outer join elke WHERE-test op de optionele zijde en controleer wat die met een met NULL-waarden aangevulde rij doet.

Belangrijkste punten

  • ON bepaalt de overeenkomsten; WHERE filtert voltooide resultaatrijen.
  • Zet een beperking op de rechterkant in ON om linkerrijen zonder geschikte overeenkomst te behouden.
  • Zet rapportbeperkingen op de linkerkant in WHERE.
  • Een vergelijking op de rechterkant in WHERE verwijdert met NULL-waarden aangevulde rijen als de vergelijking onbekend is.
  • De anti-jointest IS NULL wordt bewust na de join uitgevoerd.
4

Selfjoins en cross joins

Met dezelfde jointechniek kun je twee rollen in één tabel verbinden of alle combinaties van twee tabellen maken. Query's over werknemers en leidinggevenden hebben aliassen nodig die de rollen duidelijk houden; collega-paren hebben ook een regel nodig voor koppelingen aan zichzelf en omgekeerde dubbele paren. Cross joins genereren bewust alle mogelijkheden, zoals maten en kleuren. Door hun omvang te voorspellen, herken je wanneer die vermenigvuldiging de bedoeling was en wanneer een voorwaarde ontbreekt.

4.1 Twee rollen voor één tabel

De leidinggevende van een werknemer is ook een werknemer. Een selfjoin leest dezelfde tabel onder verschillende aliassen, zodat de ene rij de werknemer en de andere de leidinggevende kan voorstellen. Een selfjoin gebruikt gewone joinsyntaxis; er is geen trefwoord SELF JOIN.

Benoem de rollen vóór de kolommen

De werknemersgegevens zijn:

emp_idnamemanager_id
1GraceNULL
2Hassan1
3Iris1
4Jamal2
SELECT e.name AS employee, m.name AS manager
FROM employees e
JOIN employees m ON e.manager_id = m.emp_id;

e levert de werknemersrij. De manager_id daarvan verwijst naar de emp_id van de leidinggevende in rol m. Hassan verwijst naar 1 en wordt dus aan Grace gekoppeld; ook Iris wordt aan Grace gekoppeld. Jamal verwijst naar 2 en wordt aan Hassan gekoppeld. Het resultaat is (Hassan, Grace), (Iris, Grace) en (Jamal, Hassan).

Grace heeft geen leidinggevende. Haar manager_id is NULL, dus de inner join sluit haar uit. Als je JOIN vervangt door LEFT JOIN, wordt (Grace, NULL) toegevoegd en krijg je vier rijen. Door verschillende aliassen kan de database de rollen onderscheiden, ook al komen beide invoertabellen uit dezelfde opgeslagen tabel.

Stel de vraag in de andere richting

Om mensen te vinden die aan niemand leidinggeven, begin je bij de rol van leidinggevende en zoek je naar een ontbrekende werknemer:

SELECT m.name
FROM employees m
LEFT JOIN employees e ON e.manager_id = m.emp_id
WHERE e.emp_id IS NULL;

Dit retourneert (Iris) en (Jamal). Grace heeft een overeenkomst met Hassan en Iris; Hassan heeft een overeenkomst met Jamal. Iris en Jamal hebben geen directe ondergeschikten. Door na de join de werknemerssleutel te testen, vind je hun ontbrekende tegenhanger.

Een derde alias volgt nog één niveau. Als je hun namen selecteert, retourneert employees e JOIN employees m ON e.manager_id = m.emp_id JOIN employees g ON m.manager_id = g.emp_id (Jamal, Hassan, Grace). Elke extra rol volgt nog één schakel. Een vaste query bereikt een vast aantal niveaus; een hiërarchie van willekeurige diepte heeft een recursieve query nodig.

Koppel collega's eenmaal aan elkaar

Dezelfde tabel kan ook paren collega's opleveren:

SELECT a.name, b.name
FROM employees a
JOIN employees b
  ON a.manager_id = b.manager_id
 AND a.emp_id < b.emp_id;

Hassan en Iris hebben leidinggevende 1 gemeen. De kleiner-dantest sluit uit dat een persoon aan zichzelf wordt gekoppeld en behoudt slechts één volgorde van elk paar. Het resultaat is (Hassan, Iris).

Met alleen de gelijkheid van leidinggevenden heeft het resultaat vijf rijen: Hassan–Hassan, Hassan–Iris, Iris–Hassan, Iris–Iris en Jamal–Jamal. De NULL-sleutel van Graces leidinggevende komt met niets overeen, ook niet met een andere NULL. Als je < vervangt door <>, sluit je koppelingen aan zichzelf uit, maar behoud je zowel (Hassan, Iris) als (Iris, Hassan). Kies < als de vraag elk ongeordend paar eenmaal vereist.

Belangrijkste punten

  • Gebruik verschillende aliassen voor de verschillende rollen in een selfjoin.
  • Koppel de manager_id van een werknemer aan de emp_id van de rol van leidinggevende.
  • Een left selfjoin kan de top van een hiërarchie behouden.
  • Elke extra selfjoin volgt een volgend vast niveau.
  • Voor paren uit dezelfde groep verwijdert < koppelingen aan zichzelf en omgekeerde dubbele paren; <> verwijdert alleen koppelingen aan zichzelf.

4.2 Elke mogelijke combinatie

Een cross join maakt elk paar rijen, zonder koppelingsvoorwaarde. Dit is nuttig als de vraag om mogelijkheden vraagt, zoals elke combinatie van maat en kleur die een winkel op voorraad kan hebben.

Maak de combinatielijst

sizes bevat S, M en L. colors bevat Red en Blue.

SELECT s.size, c.color
FROM sizes s
CROSS JOIN colors c;

De zes paren zijn (S, Red), (S, Blue), (M, Red), (M, Blue), (L, Red) en (L, Blue). Elke maat verschijnt naast beide kleuren. Dit zijn de resultaatrijen; hun weergavevolgorde is zonder ORDER BY niet gegarandeerd.

Vermenigvuldig bij twee invoertabellen hun aantallen rijen. Drie maten en twee kleuren geven zes rijen. Met een derde tabel die vier opties bevat, heeft het resultaat 24 rijen. Als een invoertabel leeg is, kan er geen volledige combinatie worden gemaakt en heeft het resultaat nul rijen.

Begin met een volledig rapportageraster

Verkooprecords tonen alleen combinaties die zijn voorgekomen. Om elke winkel in elke maand te tonen, maak je eerst een raster met stores CROSS JOIN months. Gebruik daarna een left join om overeenkomende verkooprecords te koppelen:

SELECT s.store_id, m.month, x.total
FROM stores s
CROSS JOIN months m
LEFT JOIN sales x
  ON x.store_id = s.store_id
 AND x.month = m.month;

Het raster behoudt een winkel-maandpaar ook als er geen verkoop is, met NULL in x.total. Beide sleuteldelen zijn van belang: als je alleen de winkel vergelijkt, koppel je ook de verkopen van die winkel uit andere maanden. De cross join bepaalt welke combinaties het rapport moet tonen en de left join levert de beschikbare gegevens daarover.

Herken een onbedoelde cross join

FROM customers, orders zonder koppelingsvoorwaarde maakt 16 paren van de vier klanten en vier bestellingen. Ana wordt gekoppeld aan haar eigen bestellingen, Bens bestelling en de gastbestelling. Voor elke klant gebeurt hetzelfde. Dat is alleen nuttig als elke klant-bestelcombinatie ook echt gewenst is.

Een groot aantal rijen is een aanwijzing, maar bekijk ook de koppelingen. Met 1.000 klanten en 1.000 producten maakt een bewuste cross join 1.000.000 rijen. Een join met een verkeerde maar selectieve voorwaarde kan ook een kleiner, onjuist resultaat opleveren. Vergelijk het aantal en de betekenis van elk paar met de vraag.

Herken gelijkwaardige vormen

CROSS JOIN, een kommajoin zonder koppelingsvoorwaarde en een inner join met ON 1 = 1 behouden allemaal elk paar. SQLite en MySQL accepteren ook een gewone JOIN zonder ON en behandelen die als een cross join; PostgreSQL vereist ON of USING bij een gewone join. Schrijf CROSS JOIN als elke combinatie bewust is bedoeld.

DISTINCT verwijdert identieke geselecteerde rijen, geen onjuiste relaties. Als een onbedoelde cross join Ana aan Bens bestelling koppelt, blijven die waarden als een unieke rij bestaan. Herstel de ontbrekende voorwaarde in plaats van een deel van de herhaalde uitvoer te verbergen.

Belangrijkste punten

  • Een cross join retourneert elke combinatie; vermenigvuldig de aantallen invoerrijen.
  • Een lege invoertabel maakt het Cartesisch product leeg.
  • Een cross join kan een volledig raster voor een latere left join maken.
  • Een ontbrekende koppelingsvoorwaarde kan een onbedoelde cross join veroorzaken.
  • DISTINCT verwijdert geen verkeerde koppelingen.
5

Koppeltabellen en langere paden

Sommige rapporten hebben een route door meerdere tabellen nodig voordat de gevraagde gegevens samenkomen. Inschrijvingsrijen verbinden studenten met cursussen en orderregels verbinden bestellingen met producten. Volg telkens één sleutel, houd bij wat elke uitvoerrij vertegenwoordigt en kies welke koppelingen vereist zijn. Een left join vroeg in een keten kan de rijen zonder overeenkomst bij een latere stap verliezen. Daarom moet de hele route de records behouden die het rapport nodig heeft.

5.1 Een veel-op-veelkoppeling volgen

Een student kan meerdere cursussen volgen en een cursus kan meerdere studenten hebben. Een koppeltabel legt deze veel-op-veelkoppelingen als afzonderlijke paren vast. De tabel wordt ook een brug-, verbindings- of associatietabel genoemd.

Lees één koppeling per rij

De voorbeeldgegevens bevatten studenten 1 Mia, 2 Noah en 3 Omar; cursussen 10 Algebra, 20 Biology en 30 Chemistry; en inschrijvingsparen (1, 10), (1, 20) en (2, 10).

student_idcourse_id
110
120
210

Student 1 verschijnt tweemaal omdat Mia twee cursussen volgt. Cursus 10 verschijnt tweemaal omdat Algebra twee studenten heeft. Geen van beide kolommen hoeft afzonderlijk uniek te zijn. Het paar kan een samengestelde primaire sleutel vormen, PRIMARY KEY (student_id, course_id), die voorkomt dat dezelfde student tweemaal voor dezelfde cursus wordt ingeschreven.

Een koppeling kan eigen gegevens hebben. enrolled_on hoort bij de inschrijving omdat het beschrijft wanneer een bepaalde student aan een bepaalde cursus begon. Evenzo beschrijft order_items.quantity hoeveel van een bepaald product bij een bepaalde bestelling hoort.

Ga met twee joins via de koppeltabel
SELECT s.name, c.title
FROM students s
JOIN enrollments e ON e.student_id = s.student_id
JOIN courses c ON c.course_id = e.course_id;

De eerste voorwaarde koppelt de inschrijvingsrijen van elke student. De tweede vervangt de cursusverwijzing van elke inschrijving door gegevens uit de cursustabel. Het volledige resultaat is (Mia, Algebra), (Mia, Biology) en (Noah, Algebra). Elke rij staat voor één inschrijving.

Geen van beide eindtabellen bevat een sleutel van student naar cursus. Als je s.student_id = c.course_id vergelijkt, vergelijk je niet-gerelateerde identificatiewaarden en sla je de inschrijvingsgegevens over. De koppeltabel levert de relatie.

Hetzelfde pad werkt in beide richtingen. Voeg WHERE c.title = 'Algebra' toe om (Mia, Algebra) en (Noah, Algebra) te krijgen. Voeg in plaats daarvan WHERE s.name = 'Mia' toe om (Mia, Algebra) en (Mia, Biology) te krijgen. De koppelingen blijven hetzelfde; het filter kiest welke koppelingen de vraag beantwoorden.

Neem personen of cursussen zonder koppelingen mee

Begin aan de kant die behouden moet blijven. students s LEFT JOIN enrollments e ON e.student_id = s.student_id behoudt Omar met NULL in de inschrijvingskolommen. Om cursustitels te tonen en hem te behouden, moet ook de latere join van inschrijvingen naar cursussen de ontbrekende inschrijving behouden.

Om cursussen te vinden die niemand volgt, gebruik je de cursuskant en een anti-join:

SELECT c.title
FROM courses c
LEFT JOIN enrollments e ON e.course_id = c.course_id
WHERE e.student_id IS NULL;

Dit retourneert (Chemistry). Bij een echte overeenkomende inschrijving maakt student_id deel uit van de primaire sleutel en kan het geen NULL zijn. De test herkent dus de ontbrekende koppeling.

Sla één relatie per koppelrij op. Een tekstlijst zoals “10,20” in één studentenveld kan bij een gelijkheidsvergelijking niet overeenkomen met afzonderlijke cursus-ID's 10 en 20. Dankzij afzonderlijke paren kan elke joinvoorwaarde één verwijzing met één sleutel vergelijken.

Belangrijkste punten

  • Een koppelrij legt één paar vast en kan gegevens over die relatie bevatten.
  • De twee refererende sleutels kunnen een samengestelde sleutel vormen die dubbele paren voorkomt.
  • Twee joins verbinden de eindtabellen via de koppeltabel.
  • Begin bij het eindpunt dat behouden moet blijven als je ontbrekende relaties zoekt.

5.2 Een pad door vier tabellen

Een langere join volgt dezelfde regel als een join tussen twee tabellen: koppel de volgende tabel met een zinvolle voorwaarde. Volg voordat je de query schrijft de sleutels en bepaal wat één resultaatrij moet vertegenwoordigen.

Voeg de gedetailleerde winkelgegevens toe
product_idnameprice
1Mug8,00
2Pen1,50
3Notebook4,25
4Stapler12,00

De orderregels (order_id, product_id, quantity) zijn (101, 1, 2), (101, 2, 4), (102, 3, 6), (103, 1, 6), (103, 2, 8) en (104, 2, 10). Elke regel koppelt een bestelling aan een product en legt een aantal vast.

Volg voor de vraag “Wat heeft elke klant gekocht?” customers → orders → order_items → products. De sleutels langs het pad zijn klant-ID, bestel-ID en product-ID. Vier tabellen langs deze keten vereisen drie koppelingen.

Koppel telkens één nieuwe tabel
SELECT c.name, o.order_id, p.name AS product,
       oi.quantity, oi.quantity * p.price AS line_total
FROM customers c
JOIN orders o ON o.customer_id = c.customer_id
JOIN order_items oi ON oi.order_id = o.order_id
JOIN products p ON p.product_id = oi.product_id
ORDER BY o.order_id, p.product_id;

Elke ON verwijst naar de nieuw geïntroduceerde tabel en een tabel die al beschikbaar is. Producten worden via orderregels gekoppeld, niet rechtstreeks via klanten. Het resultaat is:

nameorder_idproductquantityline_total
Ana101Mug216,00
Ana101Pen46,00
Ana102Notebook625,50
Ben103Mug648,00
Ben103Pen812,00

De eerste join sluit gastbestelling 104 uit omdat de klantverwijzing NULL is. De overige drie bestellingen bevatten vijf regels, dus het eindresultaat heeft vijf rijen. Voor bestelling 101 kosten twee mokken 16,00 en vier pennen 6,00, samen gelijk aan het ordertotaal van 22,00.

Weet wat een rij telt

Eén resultaatrij vertegenwoordigt een orderregel. Ana en bestelling 101 verschijnen tweemaal omdat die bestelling twee producten heeft. Herhaalde klantnamen zijn dus te verwachten. Als je deze rijen telt, tel je regels, geen unieke klanten of bestellingen.

Een filter mag naar elke gekoppelde tabel verwijzen. Als je WHERE p.name = 'Pen' vóór ORDER BY toevoegt, blijven (Ana; 101; Pen; 4; 6,00) en (Ben; 103; Pen; 8; 12,00) over. Geen productfilter kan de gastbestelling terughalen die al bij de klantkoppeling is uitgesloten.

Houd elke koppeling zichtbaar

Bij een keten van inner joins kan de geschreven tabelvolgorde veranderen zonder de overeenkomende combinaties te veranderen, mits elke voorwaarde alleen verwijst naar tabellen die al zijn geïntroduceerd. Beginnen bij het onderwerp van het rapport en de sleutels volgen is meestal het gemakkelijkst te lezen.

Een ontbrekende voorwaarde kan een tussenresultaat vermenigvuldigen in SQLite of MySQL, die een gewone JOIN zonder ON accepteren. PostgreSQL en SQL Server wijzen die syntaxis af. Ook een ontbrekende voorwaarde in een kommaquery kan bij die stap elke combinatie opleveren.

Soms vervult één tabel twee rollen. Een vluchtrapport kan airports als dep koppelen op dep.code = f.from_code en nogmaals als arr op arr.code = f.to_code. Verschillende aliassen geven de vertrek- en aankomstgegevens afzonderlijke plaatsen in het resultaat.

Belangrijkste punten

  • Voeg één joinvoorwaarde toe voor elke schakel in het tabelpad.
  • Elke ON mag de nieuwe tabel en al geïntroduceerde tabellen gebruiken.
  • Bepaal wat één uitvoerrij vertegenwoordigt voordat je waarden telt of optelt.
  • Een tabel kan onder verschillende aliassen voorkomen als het rapport verschillende rollen nodig heeft.

5.3 Optionele rijen behouden in een keten

Een left join behoudt rijen bij één stap. Latere joins en filters werken nog steeds op het resultaat van die stap. Om een ouder zonder overeenkomst op een langer pad te behouden, volg je wat er bij elke stap met de met NULL-waarden aangevulde kolommen gebeurt.

Bekijk waar een behouden rij verdwijnt
SELECT c.name, o.order_id, oi.product_id
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
JOIN order_items oi ON oi.order_id = o.order_id;

De eerste stap maakt vijf rijen: Ana's twee bestellingen, Bens bestelling en elk één met NULL-waarden aangevulde rij voor Chloe en Dev. Bij de volgende stap zijn de waarden van o.order_id voor Chloe en Dev NULL. Ze kunnen niet voldoen aan de gelijkheid met een orderregelsleutel, dus verwijdert de inner join ze. De query retourneert vijf orderregelrijen en verliest beide klanten zonder bestellingen.

Behoud het optionele pad
SELECT c.name, o.order_id, oi.product_id
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
LEFT JOIN order_items oi ON oi.order_id = o.order_id;

Nu behoudt de tweede join ook die met NULL-waarden aangevulde rijen. Het resultaat bevat (Ana, 101, 1), (Ana, 101, 2), (Ana, 102, 3), (Ben, 103, 1), (Ben, 103, 2), (Chloe, NULL, NULL) en (Dev, NULL, NULL): zeven rijen.

Als latere joins afhangen van kolommen van een optionele tabel, moeten het meestal left joins blijven om ontbrekende tegenhangers te behouden. Een latere inner join op kolommen van een verplichte tabel heeft een andere rol, dus onderzoek de daadwerkelijke afhankelijkheid in elke voorwaarde.

Volg dezelfde regel via een koppeltabel
SELECT s.name, c.title
FROM students s
LEFT JOIN enrollments e ON e.student_id = s.student_id
LEFT JOIN courses c ON c.course_id = e.course_id;

Dit retourneert (Mia, Algebra), (Mia, Biology), (Noah, Algebra) en (Omar, NULL). Als je van de laatste join een inner join maakt, verdwijnt Omar omdat zijn ontbrekende inschrijving niet met een cursus kan overeenkomen.

Haakjes bieden een andere manier om de groepering uit te drukken: students s LEFT JOIN (enrollments e JOIN courses c ON c.course_id = e.course_id) ON e.student_id = s.student_id. De overeenkomsten tussen inschrijvingen en cursussen vormen de optionele groep; de outer join koppelt die groep aan elke student en behoudt zo Omar.

Controleer latere filters en de joinrichting

Als je WHERE c.title = 'Algebra' toevoegt aan de studentenquery met alleen left joins, blijven alleen Mia en Noah bij Algebra over. De vergelijking is onbekend voor Omars cursustitel met NULL. Dit beantwoordt “Wie volgt Algebra?”, maar niet meer “Toon alle studenten en hun cursussen.” Een IS NULL-test gedraagt zich anders omdat deze bewust een ontbrekende waarde accepteert.

Een latere right join verandert de behouden zijde opnieuw: hij behoudt de nieuw toegevoegde rechtertabel en eerdere rijen zonder overeenkomst kunnen verdwijnen. Zet de tabel die behouden moet blijven voorop en koppel optionele paden met left joins als dat het rapport duidelijk weergeeft.

Bouw en bekijk de query telkens één join tegelijk. Noteer zowel het aantal rijen als de sleutels die overblijven. Een dalend aantal kan weggevallen rijen zonder overeenkomst onthullen; een onverwachte stijging kan een ontbrekend sleutelonderdeel onthullen. Sommige aantallen blijven gelijk als rijen zowel wegvallen als worden vermenigvuldigd, dus bekijk ook representatieve sleutels.

Belangrijkste punten

  • Elke join werkt op het resultaat dat tot dan toe is opgebouwd.
  • Een inner join via een NULL-sleutel van een optionele tabel verwijdert rijen zonder overeenkomst.
  • Houd latere afhankelijke koppelingen optioneel als hun ontbrekende rijen behouden moeten blijven.
  • Een latere WHERE-vergelijking kan nog steeds rijen verwijderen die door left joins zijn behouden.
  • Bekijk na elke stap het aantal en de overgebleven sleutels.
6

Betrouwbare tellingen en resultaten

Herhaalde waarden zijn vaak een correct gevolg van een join, maar kunnen tellingen en sommen in een rapport onjuist maken. Volg hoe een ordertotaal wordt herhaald door detailrijen, kies de juiste identificatiewaarde om te tellen en onderscheid nuttig gebruik van DISTINCT van een verborgen joinfout. Controleer daarna een rapport op basis van voorspelde overeenkomsten, volledige sleutels, het gedrag van NULL en consistente sleutelnotaties voordat je op de aannemelijk ogende uitvoer vertrouwt.

6.1 Tellen en optellen op het juiste niveau

Een join kan correct zijn terwijl een aggregatie over het resultaat onjuist is. De belangrijkste vraag is wat één rij na de join vertegenwoordigt. Een waarde die eenmaal per bestelling is opgeslagen, kan meerdere keren in een lijst met orderregels verschijnen.

Volg een herhaald ordertotaal

Ana heeft bestelling 101 voor 22,00 en bestelling 102 voor 25,50. De twee bestellingen optellen geeft 47,50. Bestelling 101 heeft twee regels, dus de join met order_items herhaalt 22,00 tweemaal; bestelling 102 heeft één regel. Als je de herhaalde waarden optelt, krijg je 69,50.

SELECT c.customer_id, c.name, SUM(o.total) AS spent
FROM customers c
JOIN orders o ON o.customer_id = c.customer_id
GROUP BY c.customer_id, c.name;

GROUP BY verzamelt de rijen per klant en SUM telt de waarden van die groep op. Deze query retourneert (1; Ana; 47,50) en (2; Ben; 60,00). Als je de orderregeljoin vóór het groeperen toevoegt, wordt Ana's totaal te hoog: 69,50, en dat van Ben 120,00. De totalen van de twee klanten samen worden 189,50 in plaats van 107,50.

Over alle vier bestellingen, inclusief gastbestelling 104, zorgt een rechtstreekse join van bestellingen met hun regels ervoor dat SUM(o.total) 204,50 retourneert in plaats van 122,50. Deze rijvermenigvuldiging ontstaat door de een-op-veelkoppeling, niet door een syntaxisfout.

Sommeer gegevens op hun opgeslagen niveau

Voor ordertotalen tel je bestellingen op zonder de detailtabel toe te voegen. Voor een totaal van regelbedragen bereken je de waarde van elke regel zelf:

SELECT SUM(oi.quantity * p.price) AS sales
FROM order_items oi
JOIN products p ON p.product_id = oi.product_id;

De zes regelbedragen zijn 16,00, 6,00, 25,50, 48,00, 12,00 en 15,00. Samen zijn ze 122,50, het totaal van alle vier bestellingen. Elk product van aantal en prijs hoort bij één regel en wordt dus eenmaal opgeteld.

Tel echte overeenkomsten

Nadat klanten aan bestellingen en regels zijn gekoppeld, neemt Ana drie rijen in. COUNT(*) telt die regels; COUNT(DISTINCT o.order_id) telt haar twee unieke bestellingen.

Na alleen een left join van klanten naar bestellingen telt COUNT(*) één met NULL-waarden aangevulde rij voor Chloe en één voor Dev. Tel in plaats daarvan de optionele bestelsleutel:

SELECT c.customer_id, c.name, COUNT(o.order_id) AS orders
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id
GROUP BY c.customer_id, c.name;

Dit retourneert (1, Ana, 2), (2, Ben, 1), (3, Chloe, 0) en (4, Dev, 0). COUNT(column) negeert NULL-waarden; COUNT(*) telt rijen.

Twee veel-kanten vermenigvuldigen elkaar

Als een klant drie bestellingen en twee ondersteuningsverzoeken heeft, levert het onafhankelijk koppelen van beide kindtabellen aan die klant zes rijen op. Elke bestelling wordt aan elk verzoek gekoppeld. Gewone tellingen van beide kindsleutels worden zes. Tel unieke kindsleutels om drie en twee te krijgen, of tel de kindtabellen afzonderlijk op.

DISTINCT c.customer_id, c.name is nuttig voor een unieke klantenlijst. Door de sleutel te behouden voorkom je dat verschillende klanten met dezelfde naam worden samengevoegd. Het herstelt geen ontbrekende joinvoorwaarde. Ook SUM(DISTINCT o.total) is onbetrouwbaar: het voegt twee afzonderlijke bestellingen samen die toevallig hetzelfde bedrag hebben.

Belangrijkste punten

  • Een-op-veeljoins herhalen ouderwaarden; sommeer een gegeven op het niveau waarop het is opgeslagen.
  • COUNT(*) telt rijen; COUNT(column) slaat NULL-waarden over.
  • COUNT(DISTINCT key) telt unieke identificatiewaarden die geen NULL zijn na rijvermenigvuldiging.
  • Twee onafhankelijke joins aan de veel-kant kunnen elkaar vermenigvuldigen.
  • SUM(DISTINCT amount) kan verschillende records met gelijke bedragen samenvoegen.
  • Behoud een identificerende sleutel in een lijst met unieke entiteiten.

6.2 Overeenkomsten controleren voordat je een rapport vertrouwt

Een query kan worden uitgevoerd en toch de verkeerde relaties beschrijven. Voorspel voordat je een joinresultaat gebruikt wat behouden moet blijven, hoe vaak elke sleutel moet verschijnen en wat één resultaatrij moet betekenen.

Voorspel het aantal rijen

Als de klantverwijzing van een bestelling overeenkomt met een unieke klantsleutel, heeft elke bestelling maximaal één overeenkomende klant. Een inner join retourneert daarom maximaal één rij per bestelling. In de winkelgegevens hebben drie van de vier bestellingen een klant, dus retourneert de inner join tussen klanten en bestellingen drie rijen.

Vanaf de klantkant retourneert een left join de drie overeenkomende paren plus één rij voor Chloe en één voor Dev: vijf rijen. Een cross join van de vier klanten en vier bestellingen geeft 16. Deze voorspellingen bieden verschillende controles voor verschillende jointypen; alleen het aantal tabellen bepaalt het aantal rijen niet.

Onderzoek de vorm van een onjuist resultaat
VerschijnselWat je moet onderzoeken
Elke linkerrij wordt aan elke rechterrij gekoppeldOntbrekende voorwaarde of een voorwaarde die altijd waar is
Geen overeenkomsten of niet-gerelateerde entiteiten gekoppeldVerkeerde kolommen of onverenigbare sleutelwaarden
Eén logisch record heeft meerdere tegenhangersEen onvolledige sleutel, dubbele opzoeksleutel of verwachte een-op-veelkoppeling
Ouders zonder kinderen verdwijnenEen inner join of filter op de optionele zijde later in de query

Als je alleen store_id vergelijkt terwijl records door (store_id, month) worden geïdentificeerd, meng je verschillende maanden. Vergelijk elk onderdeel met AND. Een query die toevallig werkt zolang een winkel één maand heeft, kan misgaan zodra een tweede maand wordt ingeladen.

Onderscheid ontbrekende waarden van verkeerde sleutels

Bij gewone gelijkheid komen NULL-sleutels niet overeen, ook niet NULL met NULL. Als je bestellingen op customer_id aan zichzelf koppelt, krijg je vier paren uit Ana's twee bestellingen en één uit Bens bestelling, samen vijf rijen. De gastbestelling levert er geen op. Een outer join is nodig als een rij met een ontbrekende verwijzing behouden moet blijven.

Dubbele opzoekwaarden vermenigvuldigen alleen de overeenkomsten voor die waarden. Als een landcode tweemaal in een opzoektabel voorkomt, krijgt elke klant met die code twee bijbehorende rijen. Codes die eenmaal voorkomen, geven nog steeds één tegenhanger. Onderzoek een opzoektabel die uniek zou moeten zijn met:

SELECT code, COUNT(*) AS copies
FROM countries
GROUP BY code
HAVING COUNT(*) > 1;

GROUP BY verzamelt de rijen van elke code; HAVING behoudt groepen waarvan het aantal groter is dan één. Als je de hele opzoektabel tweemaal inlaadt, verdubbelen de rijen van elke overeenkomende klant.

Controleer ook sleuteltypen en -notaties. De tekst “0042” en het getal 42 kunnen zich per database anders gedragen: geen overeenkomst, een typefout of een automatische conversie. SQLite kan een TEXT-kolom met “0042” koppelen aan een INTEGER-kolom met 42. Gebruik consistente sleuteltypen en -notaties of een expliciete conversie die past bij de bedoelde betekenis.

Doorloop de eisen van het rapport

Vraag je af welke tabel alle rijen moet behouden. Volg het volledige sleutelpad en controleer elke voorwaarde aan de hand van het schema. Bepaal waarom elke koppeling een inner of outer join is en controleer daarna of elk filter bij het koppelen of daarna hoort. Vergelijk na elke stap de aantallen rijen en bekijk een bekende overeenkomende rij, een rij zonder overeenkomst en een rij met meerdere tegenhangers. Controleer ten slotte of elke telling en som het bedoelde soort record meet.

Belangrijkste punten

  • Voorspel aantallen op basis van de relatie en het jointype.
  • Controleer elk onderdeel van een samengestelde sleutel.
  • Gewone gelijkheid beschouwt NULL-sleutels nooit als een overeenkomst.
  • Dubbele opzoeksleutels vermenigvuldigen de betreffende overeenkomsten.
  • Houd typen en notaties van gekoppelde sleutels consistent.
  • Controleer zowel de overgebleven identificatiewaarden als de totalen en aantallen rijen.

SQL-joins: voorbeelden

6 Walkthroughs

1

Van schemakoppelingen naar gekoppelde rijen

10 stappen
Lees de sleutels van de winkel, voorspel overeenkomende paren en maak de herkomst van elke kolom duidelijk.
  1. 1
    IntroductieBegin met de vraag van het rapport

    Een rapport heeft klantnamen naast ordertotalen nodig, maar die gegevens staan in verschillende tabellen. Een join brengt de gerelateerde rijen samen.

    Zoek eerst de sleutelkoppeling. Stel je daarna de paren voor die deze mogelijk maakt. Deze volgorde helpt je het resultaat te voorspellen voordat je SQL schrijft: een naam kan zich herhalen omdat er meerdere overeenkomende bestellingen zijn en een rij kan verdwijnen omdat er geen overeenkomst is.

  2. 2
    VoorbeeldLees de klant- en bestelsleutels

    De klanten zijn 1 Ana, 2 Ben, 3 Chloe en 4 Dev. Bestellingen 101 en 102 verwijzen naar klant 1; bestelling 103 verwijst naar klant 2. Bestelling 104 is een gastbestelling met een klantverwijzing die NULL is.

    De koppeling is orders.customer_id → customers.customer_id. Het bestelnummer identificeert een aankoop, terwijl de klantverwijzing de eigenaar ervan identificeert. Als je de twee verschillende soorten ID's vergelijkt, druk je niet uit van wie de bestelling is.

  3. 3
    UitlegZet de verwijzing aan de veel-kant

    Eén klant kan meerdere bestellingen plaatsen. Elke bestelling slaat één klantverwijzing op, dus orders is de veel-kant van de koppeling.

    Bij een een-op-eenkoppeling is die verwijzing ook uniek. Bij veel-op-veelkoppelingen, zoals studenten die cursussen volgen, legt een koppeltabel de paren vast. Deze structuren laten zien welke route een rapport moet volgen en waar meerdere tegenhangers mogelijk zijn.

  4. 4
    UitdagingVind de ontbrekende route

    Je hebt de producten nodig die elke klant heeft gekocht. Het schema koppelt customers aan orders, orders aan order_items en order_items aan products. Kun je order_items overslaan en de bestel-ID rechtstreeks met de product-ID vergelijken?

    ---reveal---

    Nee. Die ID's identificeren verschillende dingen. Volg customers → orders → order_items → products. Elke rij in order_items legt een product in een bepaalde bestelling vast en levert zo de koppeling die bij de rechtstreekse vergelijking ontbreekt.

  5. 5
    VoorbeeldMaak de eerste paren

    Pas o.customer_id = c.customer_id toe. Bestelling 101 komt overeen met Ana omdat beide klantwaarden 1 zijn. Bestelling 102 vormt nog een paar met Ana en bestelling 103 komt overeen met Ben.

    De resultaatparen zijn (Ana, 101), (Ana, 102) en (Ben, 103). Chloe en Dev hebben geen tegenhanger. Gastbestelling 104 heeft een klantsleutel die NULL is, dus de gelijkheidsvoorwaarde is onbekend en levert geen overeenkomst op.

  6. 6
    KernpuntEén lijn voor elke overeenkomst

    Stel je een lijn voor tussen elke klantrij en elke bestelrij die ermee overeenkomt. Elke lijn wordt een resultaatrij. Ana heeft twee lijnen, dus haar naam verschijnt tweemaal.

    Dit beeld werkt ook als sleutels aan beide kanten worden herhaald: twee linkerrijen en drie rechterrijen met één sleutel maken zes lijnen. Overlappende cirkels kunnen die afzonderlijke koppelingen niet tonen of verklaren hoe een join langer wordt dan elk van de invoertabellen.

  7. 7
    TipGeef aan waar een kolom vandaan komt

    Geef de tabelverwijzingen aliassen, zoals customers c en orders o. Schrijf c.name voor de klantnaam en o.total voor het ordertotaal.

    Beide invoertabellen hebben customer_id. Bij JOIN ... ON is het dubbelzinnig om alleen die naam te selecteren; kwalificeer hem als c.customer_id of o.customer_id. SELECT * bevat alle zeven invoerkolommen, inclusief beide exemplaren van de sleutel. Door alleen de benodigde kolommen te selecteren, maak je het rapport smaller.

  8. 8
    UitlegKoppelen komt vóór filteren

    Lees de logische volgorde als joins, dan WHERE, dan SELECT en dan ORDER BY. Een filter kan een gekoppelde kolom gebruiken die het rapport niet toont.

    Als je bijvoorbeeld de klant-bestelparen filtert op c.city = 'Denver', blijven Ana's twee bestellingen over. Chloe woont ook in Denver, maar een inner join leverde voor haar geen rij op. Een later filter kan een rij die tijdens het koppelen is uitgesloten niet terughalen.

  9. 9
    UitdagingVoorspel een resultaat met herhaalde sleutels

    Een tabel met registraties heeft twee rijen met locatiesleutel 8. Een opzoektabel voor locaties heeft per ongeluk drie rijen met sleutel 8. Alle andere sleutels ontbreken. Hoeveel rijen retourneert hun inner join op gelijkheid en verandert dat aantal als je alleen de sleutel selecteert?

    ---reveal---

    Er worden zes rijen geretourneerd: elke registratie komt overeen met alle drie opzoekrijen. Als je alleen de sleutel selecteert, wordt elke rij smaller, maar blijven er zes rijen over, tenzij een aparte bewerking zoals DISTINCT herhaalde geselecteerde waarden verwijdert.

  10. 10
    SamenvattingLees eerst de relatie en dan de rijen

    Zoek de sleutelroute voordat je de uitvoerkolommen kiest. Een-op-veelkoppelingen kunnen ouderwaarden herhalen; een koppeltabel bevat een veel-op-veelkoppeling.

    Vraag je bij elk paar af of de voorwaarde waar is. Controleer daarna hoeveel tegenhangers elke rij heeft. Gebruik aliassen om de herkomst van kolommen te onderscheiden en houd bij het uitleggen van het resultaat het koppelen gescheiden van later filteren en sorteren.

2

Inner joins opbouwen en lezen

11 stappen
Schrijf een volledige koppelingsquery en vergelijk daarna verkorte schrijfwijzen en bereikvoorwaarden.

Sla deze les op om elke Walkthrough stap voor stap te volgen.

  1. 1
    IntroductieVereis aan beide kanten een tegenhanger
  2. 2
    VoorbeeldSchrijf de sleutelvoorwaarde
  3. 3
    VoorbeeldLees alle drie uitvoerrijen
  4. 4
    UitdagingVoeg een klantfilter toe
  5. 5
    TipVergelijk de volledige identificatie
  6. 6
    UitlegGebruik een verkorte schrijfwijze bij dezelfde naam
  7. 7
    UitdagingBekijk wat NATURAL verandert
  8. 8
    VerbandLees een oudere kommajoin
  9. 9
    VoorbeeldKoppel prijzen aan klassen
  10. 10
    UitdagingVoorspel een overlapping en een gat
  11. 11
    SamenvattingLees de voorwaarde achter de syntaxis
3

Behoud rijen zonder overeenkomst ondanks filters

14 stappen
Kies de behouden zijde en volg ON en WHERE door de resultaten van outer joins.

Sla deze les op om elke Walkthrough stap voor stap te volgen.

  1. 1
    IntroductieBepaal welke records moeten blijven
  2. 2
    VoorbeeldBehoud elke klant
  3. 3
    UitdagingVerander de kant die behouden moet blijven
  4. 4
    TipTest de sleutel van de ontbrekende tegenhanger
  5. 5
    UitlegLees een right join als een omgekeerde left join
  6. 6
    VoorbeeldBehoud records zonder overeenkomst aan beide kanten
  7. 7
    UitdagingSluit twee nieuwe sleutellijsten op elkaar aan
  8. 8
    TipControleer de ondersteuning voor outer joins
  9. 9
    VoorbeeldBeperk overeenkomende bestellingen in ON
  10. 10
    VoorbeeldVerplaats de datumtest naar WHERE
  11. 11
    UitdagingFilter de linkertabel bewust
  12. 12
    VerbandBepaal wat een weergegeven nul betekent
  13. 13
    UitdagingBehoud iedereen met recente activiteit
  14. 14
    SamenvattingHoud koppelen en filteren gescheiden
4

Volg leidinggevenden en maak combinaties

11 stappen
Gebruik rolaliassen voor selfjoins en onderscheid daarna bedoelde en onbedoelde Cartesische producten.

Sla deze les op om elke Walkthrough stap voor stap te volgen.

  1. 1
    IntroductieKies rollen of mogelijkheden
  2. 2
    VoorbeeldLees de gezagslijnen
  3. 3
    UitdagingBehoud de persoon aan de top
  4. 4
    VerbandGa nog één niveau omhoog
  5. 5
    VoorbeeldMaak elk collega-paar eenmaal
  6. 6
    VoorbeeldMaak zes shirtmogelijkheden
  7. 7
    UitdagingVoorspel het effect van een extra invoertabel
  8. 8
    KernpuntMaak een volledig rapportageraster
  9. 9
    TipHerstel de ontbrekende voorwaarde
  10. 10
    UitdagingVerbind paarregels met de productomvang
  11. 11
    SamenvattingGeef elke koppeling een duidelijk doel
5

Volg een koppeltabel en behoud een langer pad

14 stappen
Volg inschrijvingen en aankoopregels en behoud daarna ontbrekende tegenhangers via afhankelijke koppelingen.

Sla deze les op om elke Walkthrough stap voor stap te volgen.

  1. 1
    IntroductiePlan de route naar de gegevens
  2. 2
    VoorbeeldLees de inschrijvingskoppelingen
  3. 3
    VoorbeeldGa in twee stappen via de koppeltabel
  4. 4
    UitdagingVind een cursus zonder studenten
  5. 5
    UitlegVerleng de winkelroute
  6. 6
    VoorbeeldSplits bestelling 101 uit in regels
  7. 7
    VoorbeeldLees de overige aankooprijen
  8. 8
    UitdagingKies de productkoppeling
  9. 9
    VoorbeeldBekijk hoe een latere join klanten verwijdert
  10. 10
    VoorbeeldNeem de ontbrekende rij mee naar de volgende stap
  11. 11
    UitdagingBehoud de student zonder inschrijving
  12. 12
    VerbandMaak expliciet een optionele groep
  13. 13
    UitdagingControleer het filter van het voltooide rapport
  14. 14
    SamenvattingBekijk het hele pad
6

Herstel te hoge totalen en controleer het resultaat

12 stappen
Kies het juiste record om te tellen of te sommeren en onderzoek daarna problemen met sleutels en aantallen rijen.

Sla deze les op om elke Walkthrough stap voor stap te volgen.

  1. 1
    IntroductieBenoem wat wordt gemeten
  2. 2
    VoorbeeldBekijk hoe een ordertotaal wordt herhaald
  3. 3
    TipSommeer een gegeven op zijn eigen niveau
  4. 4
    UitdagingWijs een oplossing op basis van bedragen af
  5. 5
    VoorbeeldTel een identificatiewaarde of een plaatsaanduiding
  6. 6
    KernpuntTwee kindlijsten vermenigvuldigen elkaar
  7. 7
    UitlegVoorspel de omvang vóór het uitvoeren
  8. 8
    UitdagingVind een onvolledige sleutel
  9. 9
    TipControleer de opzoektabel en de sleutelnotatie
  10. 10
    VoorbeeldKoppel ontbrekende sleutels niet op gelijkheid
  11. 11
    UitdagingKies een juiste maat voor het rapport
  12. 12
    SamenvattingControleer zowel de betekenis als de aantallen

SQL-joins: oefenvragen

50 Oefenvragen in 5 sets

Set 1: Volg filters, koppelingen en herhaalde waarden10 Oefenvragen

Vraag 1 van 10

Een join met ON combineert een tabel met 4 kolommen met een tabel met 3 kolommen. Wat is de breedte van SELECT * voordat kolommen worden verwijderd?
  1. 4 kolommen
  2. 3 kolommen
  3. 12 kolommen
  4. 7 kolommen
Toon antwoordVerberg antwoord
Antwoord: D
SELECT * met JOIN ... ON bevat kolommen uit beide invoertabellen, dus vier plus drie geeft zeven kolommen. Als je de aantallen vermenigvuldigt, verwar je kolommen met rijcombinaties. Een join met USING kan genoemde gedeelde kolommen samenvoegen, maar de vraag gebruikt ON.

Vraag 2 van 10

Een bedrag van 25,00 wordt met BETWEEN low AND high aan klassen gekoppeld. De klassen zijn (0.00, 25.00) en (25.00, 50.00). Hoeveel overeenkomende klassenrijen levert het bedrag op?
  1. 0
  2. 1
  3. 2
  4. 3
Toon antwoordVerberg antwoord
Antwoord: C
BETWEEN omvat beide grenspunten, dus 25,00 hoort bij beide klassen en levert twee rijen op. Als je één bovengrens als uitgesloten beschouwt, voorspel je ten onrechte één overeenkomst. Om precies één klasse per bedrag te krijgen, moeten de bereiken een niet-overlappende regel uitdrukken.

Vraag 3 van 10

Een query gebruikt suppliers s RIGHT JOIN deliveries d ON d.supplier_id = s.supplier_id en selecteert expliciet s.name, d.delivery_id. Hoe kan de query met LEFT JOIN dezelfde paren behouden?
  1. suppliers s LEFT JOIN deliveries d ON d.supplier_id = s.supplier_id
  2. deliveries d LEFT JOIN suppliers s ON d.supplier_id = s.supplier_id
  3. deliveries d JOIN suppliers s ON d.supplier_id = s.supplier_id
  4. suppliers s FULL JOIN deliveries d ON d.supplier_id = s.supplier_id
Toon antwoordVerberg antwoord
Antwoord: B
Een right join behoudt leveringen, dus zet deliveries voorop als je deze als left join herschrijft. Behoud dezelfde voorwaarde en expliciet geselecteerde kolommen om dezelfde waarden te houden. Als je suppliers met LEFT JOIN voorop laat staan, behoud je juist leveranciers zonder overeenkomst en kunnen leveringen zonder overeenkomst wegvallen.

Vraag 4 van 10

Winkels A en B blijven behouden in een left join naar bezoeken. A heeft één bezoek vóór een grensdatum; B heeft er geen. ON behoudt alleen bezoeken op of na de grensdatum. Welke winkels blijven over als die beperking zonder verdere wijzigingen naar WHERE wordt verplaatst?
  1. Geen van beide
  2. Alleen A
  3. Alleen B
  4. Zowel A als B
Toon antwoordVerberg antwoord
Antwoord: A
Met de grensdatum in ON heeft geen van beide winkels een bezoek dat voldoet, dus krijgen beide NULL in de bezoekkolommen. Nadat de grensdatum naar WHERE is verplaatst, voldoet A's echte vroege bezoek niet aan de test en maakt B's datum met NULL de vergelijking onbekend. Beide rijen worden verwijderd; een oud bezoek levert na WHERE geen nieuwe plaatsaanduiding op.

Vraag 5 van 10

Drie werknemers hebben verschillende ID's 21, 22 en 23, allemaal met leidinggevende-ID 5. Een selfjoin koppelt gelijke leidinggevende-ID's en verschillende werknemer-ID's met <>. Hoeveel rijen worden geretourneerd en hoeveel zou < retourneren?
  1. 3 met <>; 3 met <
  2. 6 met <>; 3 met <
  3. 9 met <>; 6 met <
  4. 6 met <>; 6 met <
Toon antwoordVerberg antwoord
Antwoord: B
Elk van de drie werknemers wordt aan de andere twee gekoppeld, dus niet-gelijk geeft zes gerichte paren. Kleiner dan behoudt één volgorde van elk paar, zodat er drie overblijven. Negen tellen zou de drie koppelingen aan zichzelf omvatten, die de niet-gelijkvoorwaarde uitsluit.

Vraag 6 van 10

Een vluchtrij heeft from_code en to_code, die beide naar airports.code verwijzen. Hoe moet een rapport beide luchthavennamen ophalen?
  1. Koppel airports eenmaal op from_code en gebruik de naam opnieuw voor aankomst.
  2. Koppel airports eenmaal op beide codegelijkheden met AND.
  3. Combineer airports met een cross join en filter alleen op from_code.
  4. Koppel airports tweemaal met aliassen voor vertrek en aankomst.
Toon antwoordVerberg antwoord
Antwoord: D
Vertrek en aankomst kunnen verschillende luchthavenrijen zijn, dus heeft elk een eigen alias en koppelingsvoorwaarde nodig. Als je vereist dat één luchthavenrij gelijk is aan beide codes, werkt dat alleen als de twee codes hetzelfde zijn. Als je de vertreknaam opnieuw gebruikt, haal je geen gegevens over de aankomstluchthaven op.

Vraag 7 van 10

Alle technici moeten verschijnen met hun eventuele opdrachten en locaties. De query koppelt opdrachten met een left join en daarna locaties met een inner join via de locatie-ID van de opdracht. Waarom verdwijnen technici zonder opdracht?
  1. Hun opdrachtsleutels met NULL kunnen niet overeenkomen in de inner locatiejoin.
  2. Een left join kan slechts één technicus zonder opdracht behouden.
  3. Een locatiekolom selecteren verwijdert elke rij zonder overeenkomst.
  4. De locatiealias verbergt de primaire sleutel van de technicus.
Toon antwoordVerberg antwoord
Antwoord: A
De left join levert NULL in de opdrachtkolommen voor een technicus zonder opdracht. De latere inner join vereist een ware gelijkheid van locatiesleutels, waaraan die NULL-waarden niet kunnen voldoen. Alleen een locatiekolom selecteren zou geen rij verwijderen; de vereiste overeenkomst bij de inner join doet dat wel.

Vraag 8 van 10

Een team heeft geen taken. Wat retourneert COUNT(t.task_id) na teams LEFT JOIN tasks en groepering op team, als taak-ID's geen NULL kunnen zijn?
  1. 1
  2. NULL
  3. 0
  4. Het aantal teams
Toon antwoordVerberg antwoord
Antwoord: C
Het team zonder overeenkomst heeft een taak-ID met NULL in de behouden resultaatrij. COUNT(column) slaat NULL-waarden over en retourneert daarom nul echte taken. COUNT(*) zou voor die groep één retourneren omdat het de plaatsaanduidingsrij zelf telt.

Vraag 9 van 10

Een schrijver heeft 2 artikelen en 3 onderscheidingen, die elk onafhankelijk aan de schrijver zijn gekoppeld. Een query koppelt beide kinderen met inner joins op schrijver-ID en groepeert op schrijver. Wat zijn COUNT(article_id) en COUNT(DISTINCT award_id)?
  1. 2 en 3
  2. 6 en 6
  3. 6 en 3
  4. 3 en 2
Toon antwoordVerberg antwoord
Antwoord: C
Elk artikel wordt gekoppeld aan elke onderscheiding van die schrijver, wat zes rijen oplevert. De gewone artikeltelling telt alle zes herhalingen, terwijl de telling van unieke onderscheidingen de drie afzonderlijke onderscheidingen herkent. Als je aanneemt dat de artikeltelling twee blijft, zie je de vermenigvuldiging tussen de twee afzonderlijke veel-kanten over het hoofd.

Vraag 10 van 10

Een rapport begint met shipments s LEFT JOIN carriers c op een overeenkomende vervoerderssleutel. Eén zending heeft geen overeenkomende vervoerder en één vervoerder heeft geen zendingen. Welk record zonder overeenkomst blijft behouden?
  1. Alleen de vervoerder
  2. Alleen de zending
  3. Beide records zonder overeenkomst
  4. Geen van beide records zonder overeenkomst
Toon antwoordVerberg antwoord
Antwoord: B
Shipments is de linkerinvoer, dus de zending zonder overeenkomst blijft behouden met NULL in de vervoerdersvelden. De vervoerder zonder overeenkomst staat rechts en wordt uitgesloten. Om in deze query records zonder overeenkomst uit beide invoertabellen te behouden, is een full outer join nodig.
Set 2: Lees relaties en kies overeenkomende rijen10 Oefenvragen

Sla deze les op om elk antwoord te zien en elke set te oefenen.

Vraag 1 van 10

Een bibliotheeklid kan veel uitleningen hebben en elke uitlening hoort bij één lid. Waar moet de refererende sleutel naar het lid worden opgeslagen?
  1. In de tabel met leden
  2. In de tabel met uitleningen
  3. In beide tabellen
  4. In een aparte tabel
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 2 van 10

Twee rijen in tabel a hebben sleutel 7. Drie rijen in tabel b hebben sleutel 7. Dit zijn de enige rijen. Hoeveel rijen retourneert a JOIN b ON a.k = b.k?
  1. 2
  2. 3
  3. 5
  4. 6
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 3 van 10

rentals.customer_ref verwijst naar customers.customer_id. Verhuurrecords hebben ook een eigen rental_id. Welke ON-voorwaarde koppelt elke verhuring r aan de bijbehorende klant c?
  1. r.customer_ref = c.customer_id
  2. r.rental_id = c.customer_id
  3. r.customer_ref = r.rental_id
  4. c.customer_id = c.customer_id
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 4 van 10

De tabellen a en b bevatten elk account_id en region. Een natural join deelde voorheen alleen account_id; region is zojuist aan b toegevoegd. Waarom kan een eerder overeenkomend paar verdwijnen?
  1. De regio's komen overeen, maar de account-ID's verschillen.
  2. Door een gedeelde kolom komen alle paren overeen.
  3. De account-ID's komen overeen, maar de regio's verschillen.
  4. Door de nieuwe kolom verschijnen gedeelde ID's tweemaal.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 5 van 10

De teams zijn (1, North) en (2, South). De wedstrijden (match_id, team_id) zijn (81, 1) en (82, 1). Welke namen verschijnen vóór het filteren in een LEFT JOIN vanaf teams naar wedstrijden?
  1. North eenmaal; South eenmaal
  2. North tweemaal; South eenmaal
  3. North tweemaal; South nooit
  4. North tweemaal; South tweemaal
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 6 van 10

Lijst A heeft de unieke sleutels 2 en 5. Lijst B heeft de unieke sleutels 5 en 8. Welke paren ontstaan bij een FULL OUTER JOIN op sleutelgelijkheid?
  1. (2, NULL), (5, 5)
  2. (5, 5), (NULL, 8)
  3. (2, NULL), (5, 5), (NULL, 8)
  4. (2, 2), (5, 5), (8, 8)
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 7 van 10

De werknemers zijn (id, manager_id): (10, NULL), (11, 10), (12, 10). Een selfjoin gebruikt a.manager_id = b.manager_id AND a.id < b.id. Welk ID-paar wordt geretourneerd?
  1. (11, 12)
  2. (10, 11)
  3. (11, 11)
  4. (12, 11)
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 8 van 10

Een studio heeft 4 ruimtes en 3 tijdstippen voor sessies. Hoeveel rijen levert een CROSS JOIN van de lijsten op?
  1. 7
  2. 4
  3. 3
  4. 12
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 9 van 10

authors(author_id) en books(book_id) zijn verbonden door book_authors(author_id, book_id). Welk pad vindt de boeken van een auteur?
  1. authors → books op gelijke ID's
  2. authors → books met CROSS JOIN
  3. book_authors → authors op book_id
  4. authors → book_authors → books
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 10 van 10

sales(store_id, month) bevat (6, March) en (6, April). targets(store_id, month) bevat dezelfde twee paren, elk eenmaal. Een query koppelt alleen op winkel-ID en retourneert vier rijen. Welke oplossing geeft één doelwaarde per verkoop?
  1. Gebruik DISTINCT op alleen de winkel-ID.
  2. Voeg gelijkheid van de twee maandkolommen toe aan ON.
  3. Vervang de inner join door een left join.
  4. Behoud alleen de eerste twee rijen met LIMIT 2.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Set 3: Behoud rijen zonder overeenkomst en volg tabelpaden10 Oefenvragen

Sla deze les op om elk antwoord te zien en elke set te oefenen.

Vraag 1 van 10

Elk bedrijfsmiddel kan maximaal één actief label hebben en elk label hoort bij maximaal één bedrijfsmiddel. Welke relatie beschrijft de twee tabellen?
  1. Een-op-veel
  2. Veel-op-veel
  3. Een-op-een
  4. Alle koppelingen
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 2 van 10

invoices bevat (invoice_id, client_id): (301, 9), (302, NULL), (303, 12). clients heeft de unieke ID's 9 en 12. Welke factuur-ID's blijven behouden bij een inner join op klant-ID?
  1. 301 en 303
  2. 301, 302 en 303
  3. Alleen 302
  4. Alleen 301
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 3 van 10

Een bureau kan meerdere reserveringen hebben. Reserverings-ID's kunnen geen NULL zijn, maar note mag NULL zijn. Welke WHERE-test vindt na desks LEFT JOIN reservations alleen bureaus zonder reservering?
  1. r.note IS NULL
  2. r.reservation_id = NULL
  3. r.note IS NOT NULL
  4. r.reservation_id IS NULL
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 4 van 10

Een rapport moet elke afdeling tonen en alleen actieve werknemers koppelen. Het begint met departments d LEFT JOIN employees e ON e.department_id = d.department_id. Waar moet e.active = 1 staan?
  1. Als voorwaarde in WHERE
  2. Als extra AND-voorwaarde in ON
  3. Als de ORDER BY-expressie
  4. Als vervanging van de sleutelvergelijking
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 5 van 10

Een CROSS JOIN combineert een tabel met 8 rijen en een lege tabel. Hoeveel rijen worden geretourneerd?
  1. 8
  2. 1
  3. 9
  4. 0
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 6 van 10

memberships(member_id, club_id) legt vast dat een lid zich bij een club aansluit. Waar hoort joined_on, de datum van dat specifieke lidmaatschap?
  1. In memberships
  2. In members
  3. In clubs
  4. In een door komma's gescheiden clublijst
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 7 van 10

Een rapport volgt clients → invoices → lines → services. Elke pijl is een sleutelkoppeling en elke dienstrij is uniek op dienst-ID. Wat vertegenwoordigt één detailresultaatrij als elke koppeling overeenkomt?
  1. Eén klant
  2. Eén factuur
  3. Eén factuurregel
  4. Eén dienst in de catalogus
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 8 van 10

Er zijn vestigingen 1 en 2. Vestiging 1 heeft één opdracht met twee taakrijen; vestiging 2 heeft geen opdrachten. Een keten gebruikt branches LEFT JOIN jobs en daarna INNER JOIN tasks via de opdrachtsleutel. Hoe verandert het aantal rijen als je van de taakjoin een LEFT JOIN maakt?
  1. Het blijft 2.
  2. Het stijgt van 2 naar 3.
  3. Het stijgt van 2 naar 4.
  4. Het daalt van 3 naar 2.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 9 van 10

Eén project heeft twee facturen van elk 40,00. De eerste factuur heeft twee regels en de tweede drie. Wat zijn SUM(total) en SUM(DISTINCT total) na het koppelen van facturen aan regels?
  1. 80,00 en 80,00
  2. 200,00 en 80,00
  3. 200,00 en 40,00
  4. 80,00 en 40,00
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 10 van 10

Een regio-opzoektabel moet één rij per code hebben. Sommige gekoppelde klanten verschijnen tweemaal. Welke controlequery vindt herhaalde opzoekcodes?
  1. SELECT code, COUNT(*) FROM regions GROUP BY code HAVING COUNT(*) > 1;
  2. SELECT DISTINCT code FROM regions;
  3. SELECT code, COUNT(*) FROM regions GROUP BY code HAVING COUNT(*) = 1;
  4. SELECT code FROM regions WHERE code IS NULL;
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Set 4: Onderzoek onvolledige koppelingen en ontbrekende rijen10 Oefenvragen

Sla deze les op om elk antwoord te zien en elke set te oefenen.

Vraag 1 van 10

workers.supervisor_ref verwijst naar workers.worker_id. Werknemers hebben ook een kolom name. Wat moet de werknemersalias w aan de leidinggevendenalias s koppelen?
  1. w.supervisor_ref = s.worker_id
  2. w.worker_id = s.supervisor_ref
  3. w.name = s.name
  4. w.worker_id = s.worker_id
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 2 van 10

Een joinvoorwaarde is waar voor 4 kandidaat-rijparen, onwaar voor 3 en onbekend voor 2. Hoeveel rijen retourneert de inner join?
  1. 6
  2. 4
  3. 7
  4. 9
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 3 van 10

Een query koppelt betalingen p met een inner join aan accounts a op account-ID. De query selecteert alleen a.name, p.amount. Moet account-ID ook worden geselecteerd om de join te laten werken?
  1. Ja; beide account-ID-kolommen moeten worden geselecteerd.
  2. Ja; minstens één account-ID-kolom moet worden geselecteerd.
  3. Nee; SELECT voegt beide account-ID's automatisch toe.
  4. Nee; ON kan kolommen gebruiken die niet in SELECT staan.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 4 van 10

De tabellen a(id, label) en b(id, label) hebben respectievelijk de rijen (1, red), (2, blue) en (1, red), (2, green). Hoeveel rijen worden geretourneerd met JOIN ... USING (id) en met NATURAL JOIN?
  1. 1 met USING; 1 met NATURAL
  2. 2 met USING; 2 met NATURAL
  3. 2 met USING; 1 met NATURAL
  4. 4 met USING; 2 met NATURAL
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 5 van 10

De regio's East en West hebben elk één kantoor. Een LEFT JOIN die alle regio's behoudt, bevat AND r.name = 'East' in ON. Welke rijen verschijnen als je regio en kantoor selecteert?
  1. East met zijn kantoor; West met NULL
  2. East met zijn kantoor; West ontbreekt
  3. East met zijn kantoor; West met zijn kantoor
  4. East met NULL; West met NULL
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 6 van 10

De werknemers zijn (id, boss_id): (31, NULL), (32, 31), (33, 32), (34, 32). Welke ID-drietallen worden geretourneerd door inner joins op e.boss_id = m.id en m.boss_id = g.id?
  1. Alleen (32, 31, NULL)
  2. (31, 32, 33) en (31, 32, 34)
  3. (32, 31, NULL), (33, 32, 31), (34, 32, 31)
  4. (33, 32, 31) en (34, 32, 31)
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 7 van 10

customers → orders → order_lines → products is een sleutelpad. Een inner join van vier tabellen gebruikt elke koppeling. Waarom kan één bestel-ID in meerdere rijen verschijnen, ook als elke primaire sleutel uniek is?
  1. De primaire productsleutel moet dubbel voorkomen.
  2. Elke join retourneert alle producten voor elke bestelling.
  3. De bestelling heeft meerdere overeenkomende orderregelrijen.
  4. Unieke sleutels verhinderen een-op-veelrelaties.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 8 van 10

Zones A en B moeten beide verschijnen. A heeft één boeking die aan een echte dienst is gekoppeld; B heeft geen boekingen. De query koppelt boekingen en diensten met left joins en voegt daarna WHERE service.category = 'Repair' toe. De dienst van A is Repair. Wat blijft over?
  1. A met zijn dienst; B met NULL
  2. A met zijn dienst; B verdwijnt
  3. Beide zones met dienstvelden met NULL
  4. B met NULL; A verdwijnt
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 9 van 10

Twee abonnees heten allebei Lee, met ID's 41 en 42. De eerste heeft twee betalingen en de tweede één. Hoeveel rijen retourneren SELECT DISTINCT name en SELECT DISTINCT subscriber_id, name na een inner join met betalingen?
  1. 2 en 2
  2. 1 en 3
  3. 3 en 2
  4. 1 en 2
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 10 van 10

Een opzoektabel heeft code X tweemaal en code Y eenmaal. Eén gebeurtenis verwijst naar X en twee gebeurtenissen verwijzen naar Y. Hoeveel rijen levert hun inner join op?
  1. 4
  2. 3
  3. 5
  4. 6
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Set 5: Controleer volledige rapporten onder gewijzigde omstandigheden10 Oefenvragen

Sla deze les op om elk antwoord te zien en elke set te oefenen.

Vraag 1 van 10

Tabel A heeft sleutelrijen 1, 1, 2. Tabel B heeft sleutelrijen 1, 1, 1, 3. Hoeveel rijen retourneert een inner join op gelijkheid?
  1. 3
  2. 7
  3. 6
  4. 12
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 2 van 10

Een tarief van 9,50 wordt met een inner join aan de klassen [0.00, 9.00], [10.00, 20.00] en [8.00, 12.00] gekoppeld met inclusieve BETWEEN-tests. Hoe verandert de uitvoer voor dit tarief als de derde klasse wordt verwijderd?
  1. Van twee rijen naar één rij
  2. Van één rij naar één rij
  3. Van drie rijen naar twee rijen
  4. Van één rij naar nul rijen
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 3 van 10

Lijst A bevat de sleutels 4, 4, 9; lijst B bevat de sleutels 4, 4, 12. Een full join op gelijkheid selecteert beide sleutelkolommen. Hoeveel rijen worden geretourneerd en hoeveel blijven over na WHERE a.k IS NULL OR b.k IS NULL?
  1. 4 totaal; 2 verschillen
  2. 6 totaal; 2 verschillen
  3. 6 totaal; 4 verschillen
  4. 9 totaal; 2 verschillen
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 4 van 10

Klanten P en Q hebben elk één oude bestelling en geen recente bestellingen; R heeft geen bestellingen. Een LEFT JOIN met alleen een sleutelvoorwaarde wordt gevolgd door WHERE o.date >= '2026-09-01' OR o.order_id IS NULL. Welke klanten blijven behouden?
  1. Alleen R
  2. P, Q en R
  3. Alleen P en Q
  4. Geen klanten
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 5 van 10

Een CROSS JOIN combineert 2 modi, 5 regio's en 4 maanden. Hoeveel combinaties levert dit op?
  1. 11
  2. 20
  3. 40
  4. 10
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 6 van 10

De leden zijn 7, 8 en 9; de clubs zijn 50 en 60. De lidmaatschapsparen zijn (7,50), (7,60) en (8,50). Een query koppelt leden met left joins aan lidmaatschappen en daarna aan clubs. Wat zijn het totale aantal rijen en de clubwaarde van lid 9?
  1. 3 rijen; NULL
  2. 4 rijen; NULL
  3. 4 rijen; 60
  4. 6 rijen; NULL
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 7 van 10

Groepen G en H moeten beide verschijnen. G heeft één aanmelding die aan een geldige les is gekoppeld; H heeft er geen. Vergelijk groups LEFT JOIN signups JOIN classes met groups LEFT JOIN (signups JOIN classes) met de bijbehorende sleutels. Wat gebeurt er met H?
  1. Alleen het gegroepeerde optionele pad behoudt H.
  2. Beide vormen behouden H.
  3. Alleen het niet-gegroepeerde pad behoudt H.
  4. Geen van beide vormen behoudt H.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 8 van 10

Een klant heeft factuur 501 voor 18,00 en factuur 502 voor 27,00. Factuur 501 heeft 3 regels; factuur 502 heeft er 2. Het rapport heeft de totale factuurwaarde en het aantal facturen nodig. Welk resultaat moet het tonen?
  1. 108,00 en 5
  2. 45,00 en 5
  3. 108,00 en 2
  4. 45,00 en 2
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 9 van 10

Een tabel slaat een identificatiewaarde in een TEXT-kolom op als “0064”; een andere slaat 64 op in een INTEGER-kolom. Wat moet je controleren voordat je in verschillende databases op hun join op gelijkheid vertrouwt?
  1. Alleen of beide tabellen evenveel rijen hebben
  2. Alleen of beide kolommen dezelfde naam hebben
  3. De sleuteltypen, notaties en het conversiegedrag
  4. Of DISTINCT alle rijen zonder overeenkomst kan verwijderen
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 10 van 10

Een ouder heeft 2 facturen en 4 zaken, die onafhankelijk via ouder-ID zijn gekoppeld. Een inner join naar beide kinderen groepeert op ouder. Wat zijn COUNT(*), COUNT(DISTINCT bill_id) en COUNT(DISTINCT case_id)?
  1. 6, 2 en 4
  2. 8, 2 en 4
  3. 8, 8 en 8
  4. 4, 2 en 4
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Kom je niet uit je eigen opgave? Huiswerkhulp

Kernbegrippen

58 Kernbegrippen, elk met een definitie

A

Aansluitcontrole
Een aansluitcontrole vergelijkt records die moeten overeenstemmen, zet overeenkomende sleutels bij elkaar en maakt ontbrekende records of afwijkende waarden zichtbaar.
Een full join kan de magazijnvoorraad naast een fysieke telling plaatsen en tegelijk SKU's behouden die in een van beide lijsten ontbreken.
Aanvullende joinvoorwaarde
Een aanvullende joinvoorwaarde beperkt in ON welke kandidaat-tegenhangers in aanmerking komen, terwijl een outer join de vereiste invoerrijen blijft behouden.
Een grensdatum voor bestellingen in ON behoudt elke klant, maar koppelt alleen bestellingen die aan die grens voldoen.
Afhankelijke koppeling
Een afhankelijke koppeling verbindt een latere tabel via een kolom uit een eerder gekoppelde tabel, zodat ontbrekende eerdere tegenhangers invloed hebben op de koppeling.
Een cursusjoin hangt af van de cursus-ID van de inschrijving; een student zonder inschrijving heeft een cursus-ID met NULL dat niet aan die gelijkheid kan voldoen.
Aggregatieniveau
Een aggregatieniveau is het soort record dat een telling of som moet meten, zoals klanten, bestellingen of orderregels.
Tel unieke bestel-ID's als de gekoppelde rijen regels vertegenwoordigen, maar het rapport vraagt hoeveel bestellingen er zijn.
AND in een joinvoorwaarde
AND in een joinvoorwaarde vereist dat alle afzonderlijke tests waar zijn voordat het kandidaatpaar als overeenkomst telt.
Door zowel winkel als maand te vergelijken, voorkom je dat de aprilrij van een winkel aan de maartcijfers wordt gekoppeld.
Anti-join
Een anti-join retourneert rijen zonder overeenkomende tegenhanger. Je kunt die vinden met een left join gevolgd door een test op een ontbrekende rechtersleutel.
Koppel producten met een left join aan orderregels en test op de ontbrekende regelsleutel om onverkochte producten te vinden, zoals een nietmachine.

B

Behouden zijde
De behouden zijde van een outer join is de invoertabel waarvan rijen zonder overeenkomst moeten worden geretourneerd voordat latere joins of filters werken.
Customers is de behouden zijde in customers c LEFT JOIN orders o, ongeacht het aantal bestellingen.

C

Cartesisch product
Een Cartesisch product is de volledige verzameling combinaties die ontstaat door uit elke invoertabel één rij te kiezen.
Elke klant naast elke bestelling vormt alle mogelijke klant–bestelparen, inclusief niet-gerelateerde koppelingen.
COALESCE
COALESCE retourneert het eerste argument dat geen NULL is, zodat een resultaat een vervangingswaarde of een beschikbare sleutel uit een van beide invoertabellen kan tonen.
COALESCE(o.total, 0) toont nul als het gekoppelde ordertotaal NULL is, dus kies het kolomopschrift zorgvuldig.
COUNT(*)
COUNT(*) telt resultaatrijen, inclusief de met NULL-waarden aangevulde plaatsaanduiding van een outer join voor een ouder zonder overeenkomend kind.
Na een left join vanaf klanten draagt een klant zonder bestelling één rij bij aan COUNT(*).
COUNT(column)
COUNT(column) telt waarden die geen NULL zijn in een geselecteerde kolom en kan zo echte optionele tegenhangers na een left join tellen.
Een klant zonder bestelling heeft een gekoppelde bestelsleutel met NULL, die nul bijdraagt aan COUNT(o.order_id) in de groep van die klant.
COUNT(DISTINCT key)
COUNT(DISTINCT key) telt elke verschillende sleutel die geen NULL is eenmaal en negeert herhalingen die ontstaan doordat meerdere detailrijen overeenkomen.
Als de drie regelrijen van een klant slechts twee bestel-ID's bevatten, geeft het tellen van unieke bestel-ID's twee.
Cross join
Een cross join retourneert elk paar invoerrijen zonder koppelingsvoorwaarde en geeft daarmee het product van de aantallen rijen van de twee invoertabellen.
Drie shirtmaten gecombineerd met twee kleuren leveren zes mogelijke maat-kleurrijen voor de winkel op.

D

DISTINCT
DISTINCT verwijdert rijen die in alle geselecteerde waarden identiek zijn; het herstelt geen onjuiste relatie en ontdubbelt op zichzelf geen entiteiten.
Door unieke klant-ID en naam te selecteren, houd je verschillende personen gescheiden, ook als ze dezelfde naam hebben.
Dubbele opzoeksleutel
Een dubbele opzoeksleutel is een herhaalde waarde aan een kant die uniek zou moeten zijn, waardoor overeenkomende invoerrijen extra tegenhangers krijgen.
Als één landcode tweemaal voorkomt, levert elke klant met die code twee gekoppelde overeenkomsten in de opzoektabel op.
Dubbelzinnige kolomverwijzing
Een dubbelzinnige kolomverwijzing is een ongekwalificeerde verwijzing die een kolom in meer dan één invoertabel kan aanduiden, waardoor de herkomst onduidelijk is.
Bij JOIN ... ON mislukt het selecteren van alleen customer_id als zowel customers als orders die kolom bevat.

E

Een-op-eenrelatie
Een een-op-eenrelatie staat per rij aan beide kanten maximaal één tegenhanger toe, meestal via een refererende sleutel die ook uniek is.
Als elke werknemer maximaal één toegangspas mag hebben, dwingt een unieke werknemersverwijzing in badges die koppeling af.
Een-op-veelrelatie
Een een-op-veelrelatie staat toe dat één ouderrij meerdere kindrijen heeft, waarbij de refererende sleutel aan de kindkant is opgeslagen.
Als een klant twee bestellingen heeft, verwijzen beide bestelrijen naar het ID van die klant zonder het adres te herhalen.
Equijoin
Een equijoin koppelt rijen met gelijkheidsvergelijkingen, vaak tussen een refererende sleutel en de primaire of unieke sleutel waarnaar deze verwijst.
Klant-ID 1 in een bestelling is gelijk aan klant-ID 1 in de overeenkomende klantrij, dus voldoet dat paar aan de equijoin.

F

Filter na de join
Een filter na de join wordt in WHERE toegepast op rijen die door de join zijn opgebouwd en kan zowel overeenkomende rijen als met NULL-waarden aangevulde outer-joinrijen verwijderen.
Een datumvergelijking op de rechterkant in WHERE verwijdert een klant zonder bestellingen, omdat de gekoppelde besteldatum van die klant NULL is.
Full outer join
Een full outer join retourneert overeenkomende paren en behoudt rijen zonder overeenkomst uit beide invoertabellen met NULL-waarden voor elke ontbrekende tegenhanger.
Een full join tussen klanten en bestellingen behoudt klanten zonder bestellingen en gastbestellingen zonder klanten naast de overeenkomende bestellingen.

G

Gekwalificeerde kolomnaam
Een gekwalificeerde kolomnaam bevat een tabelnaam of alias vóór de kolom en geeft aan welke invoertabel de waarde levert.
c.customer_id selecteert de sleutel aan de klantkant als beide gekoppelde tabellen customer_id bevatten.
Gemengde joinketen
Een gemengde joinketen combineert inner en outer joins, waarbij je bij elke stap moet controleren welke eerdere rijen kunnen worden verwijderd.
Een left join naar bestellingen gevolgd door een inner join naar orderregels verwijdert klanten van wie de bestelsleutel NULL is.

H

Hiërarchie
Een hiërarchie is een structuur van ouder-kindkoppelingen, zoals gezagslijnen tussen werknemers, die een selfjoin niveau voor niveau kan volgen.
Jamal rapporteert aan Hassan, die aan Grace rapporteert; drie tabelrollen kunnen deze keten van twee koppelingen tonen.

I

Inner join
Een inner join retourneert elk paar dat aan de joinvoorwaarde voldoet en sluit rijen uit beide invoertabellen uit waarvoor geen overeenkomst wordt gevonden.
Als Ana twee bestellingen heeft en Ben één, retourneert een inner join van klanten en bestellingen die drie bestellingen en laat een gastbestelling weg.
Inschrijving
Een inschrijving koppelt één student aan één cursus en kan worden weergegeven met één koppelrij met die twee identificerende sleutels.
Mia's cursussen Algebra en Biology vereisen afzonderlijke inschrijvingsrijen; Omar heeft geen inschrijvingsrij.
IS NULL-test
Een IS NULL-test is waar als een waarde NULL is en kan ontbrekende tegenhangers na een outer join selecteren als je de test op een geschikte sleutel toepast.
De test o.order_id IS NULL behoudt klanten zonder bestellingen; de test o.order_id = NULL behoudt geen rijen.

J

Join
Een join combineert invoerrijen tot resultaatrijen volgens een koppelingsregel en kan rijen zonder overeenkomst optioneel behouden met NULL-waarden.
De naam van een klant en het totaal van een bestelling kunnen samen verschijnen nadat hun rijen op klant-ID zijn gekoppeld.
Join tussen haakjes
Een join tussen haakjes groepeert gekoppelde invoertabellen expliciet, zodat een groep met een inner join als één optionele zijde van een outer join kan dienen.
Inschrijvingen die aan cursussen zijn gekoppeld, kunnen een groep vormen die daarna met een left join aan alle studenten wordt gekoppeld, inclusief studenten zonder inschrijving.
Joinketen
Een joinketen koppelt meerdere tabellen in een query, waarbij elke nieuwe join werkt op de rijen die door de voorgaande joins zijn opgebouwd.
Als een join van klanten en bestellingen drie paren oplevert en die bestellingen vijf regels hebben, breidt het koppelen van orderregels die uit tot vijf detailrijen.
Joinpad
Een joinpad is een reeks zinvolle koppelingen tussen de tabellen die voor een query nodig zijn, met een voorwaarde voor elke koppeling.
Het aankooprapport volgt klanten naar bestellingen, vervolgens orderregels en daarna producten om productnamen te bereiken.
Joinvoorwaarde
Een joinvoorwaarde is de expressie die bepaalt of een paar overeenkomt; alleen een waar resultaat telt als overeenkomst.
o.customer_id = c.customer_id koppelt bestelling 101, met klant-ID 1, aan de klantrij waarvan het ID ook 1 is.

K

Kommajoin
Een kommajoin noemt tabellen in FROM gescheiden door komma's en drukt hun koppelingsvoorwaarde uit in de WHERE-clausule van de query.
Als je de test op klantsleutel uit een kommajoin van vier klanten en vier bestellingen verwijdert, wordt elke klant aan elke bestelling gekoppeld.
Koppeling van een rij aan zichzelf
Een koppeling van een rij aan zichzelf ontstaat als een selfjoinvoorwaarde toestaat dat beide aliassen naar dezelfde identificerende sleutel verwijzen.
Een werknemersrij wordt aan zichzelf gekoppeld als een selfjoinvoorwaarde alleen controleert of de leidinggevende-ID's van beide aliassen gelijk zijn.
Koppeltabel
Een koppeltabel legt één rij per relatiepaar vast en bevat een refererende sleutel naar elk eindpunt van een veel-op-veelkoppeling.
Elke inschrijvingsrij koppelt één student aan één cursus, zodat zowel studenten als cursussen kunnen worden herhaald.

L

Left outer join
Een left outer join behoudt elke linkerrij en retourneert elk overeenkomend paar of één rij met NULL-waarden aan de rechterkant als geen tegenhanger overeenkomt.
Een klant die nooit heeft besteld, blijft in een met een left join gekoppeld klantrapport staan, met NULL in de bestelkolommen.

M

Met NULL-waarden aangevulde rij
Een met NULL-waarden aangevulde rij is een outer-joinresultaat dat een invoerrij zonder overeenkomst behoudt en NULL levert voor de kolommen van de ontbrekende tegenhanger.
Het bestelnummer met NULL van een klant in een left join-resultaat duidt op een ontbrekende bestelpartner; het is geen opgeslagen bestelling.

N

Natuurlijke join
Een natuurlijke join vergelijkt automatisch alle kolomnamen die de invoertabellen delen, zodat wijzigingen in gedeelde namen het resultaat kunnen veranderen.
Als je een kolom voor de bezorgplaats aan orders toevoegt, vergelijkt een natuurlijke join zowel plaatsen als klant-ID's.
Niet-equijoin
Een niet-equijoin koppelt rijen met een andere vergelijking dan gelijkheid, bijvoorbeeld als een prijs tussen de onder- en bovengrens van een klasse valt.
Een mok met een prijs van 8,00 valt in de prijsklasse met de naam Standard en wordt aan het label van die klasse gekoppeld.

O

ON-clausule
Een ON-clausule geeft de koppelingsvoorwaarde voor een join en kan meerdere vergelijkingen combineren die voor een paar moeten gelden.
Een voorwaarde die verzendingen aan orderregels koppelt, gebruikt zowel bestel-ID als product-ID om de juiste tegenhanger te identificeren.
Onbedoelde cross join
Een onbedoelde cross join combineert elk rijpaar doordat een benodigde voorwaarde ontbreekt of altijd waar is, wat niet-gerelateerde overeenkomsten oplevert.
Door een vergeten voorwaarde verschijnt een klant naast de bestellingen van andere klanten en naast de eigen bestellingen, waardoor het resultaat groter wordt.
Onbekend vergelijkingsresultaat
Een onbekend vergelijkingsresultaat ontstaat bij gewone gelijkheid met NULL en telt niet als waar voor koppelen of filteren met WHERE.
Gastbestelling 104 heeft een klantverwijzing met NULL en kan dus via gelijkheid zelfs niet met een andere NULL overeenkomen.
Ongeordend paar
Een ongeordend paar beschouwt twee leden in beide volgordes als dezelfde koppeling; door verschillende ID's met < te vergelijken, behoud je het paar eenmaal.
Het collega-paar Hassan–Iris verschijnt eenmaal als de voorwaarde vereist dat de eerste werknemer-ID kleiner is.
Optionele zijde
De optionele zijde van een left join is de rechterinvoer, waarvan de kolommen met NULL worden gevuld als een behouden rij geen overeenkomst heeft.
Orders is optioneel in een rapport met alle klanten, dus mag een ontbrekende bestelling de klant niet verwijderen.
Orderregel
Een orderregel is een record voor een product binnen een bestelling, dat doorgaans de bestel- en productsleutel koppelt en het aantal opslaat.
Bestelling 101 heeft afzonderlijke regels voor Mug en Pen, dus worden de klant- en bestelwaarden herhaald in het detailrapport.

P

Primaire sleutel
Een primaire sleutel is een kolom of groep kolommen waarvan de waarde één rij uniek identificeert en geen NULL mag bevatten.
In een klanttabel onderscheidt customer_id het record van één klant van elk ander klantrecord.

R

Rapportageraster
Een rapportageraster is een volledige lijst van vereiste combinaties die met een cross join kan worden gemaakt en met een left join kan worden gevuld.
Door winkels met maanden te combineren, worden maanden zonder verkoop zichtbaar als de daadwerkelijke verkopen worden gekoppeld.
Refererende sleutel
Een refererende sleutel is een kolom of groep kolommen die verwijst naar een primaire of unieke sleutel in dezelfde of een andere tabel.
Meerdere bestellingen kunnen klant-ID 1 bevatten, waardoor elk van die bestellingen aan de ene klantrij met dat ID wordt gekoppeld.
Relatieattribuut
Een relatieattribuut is een gegeven over een specifieke koppeling tussen records en hoort daarom op de rij die die koppeling vertegenwoordigt.
Het aantal wordt op een orderregel opgeslagen omdat hetzelfde product in verschillende aantallen in verschillende bestellingen kan worden gekocht.
Right outer join
Een right outer join behoudt alle rechterrijen en voegt NULL-waarden aan de linkerkant toe als een rechterrij geen tegenhanger heeft die aan de voorwaarde voldoet.
Met orders aan de rechterkant blijft gastbestelling 104 met een NULL-klantverwijzing behouden, ook al kan geen klantrij ermee overeenkomen.
Rijvermenigvuldiging
Rijvermenigvuldiging herhaalt een ouderrij voor elk overeenkomend kind. Dat is nuttig voor detaillijsten, maar kan totalen op ouderniveau te hoog maken.
Als bestelling 101, met een totaal van 22,00, twee regels heeft, verschijnt die tweemaal na het koppelen van de regels, zodat dat totaal tweemaal zou worden opgeteld.

S

Samengestelde sleutel
Een samengestelde sleutel identificeert een record met meerdere kolommen samen; om een verwijzing eraan te koppelen, moet elk sleutelonderdeel overeenkomen.
Het student-cursuspaar voorkomt dubbele inschrijvingen, hoewel noch student-ID noch cursus-ID afzonderlijk uniek is.
Selfjoin
Een selfjoin koppelt een tabel onder afzonderlijke aliassen aan zichzelf, zodat de rijen verschillende rollen kunnen vervullen of met elkaar kunnen worden vergeleken.
De werknemersalias levert manager_id en de leidinggevendenalias levert de overeenkomende emp_id.

T

Tabelalias
Een tabelalias is een korte naam voor een tabelverwijzing, zodat de rol en kolomverwijzingen binnen een query duidelijk blijven.
In FROM customers c kan de query dankzij alias c naar de klantnaam verwijzen als c.name.

U

USING-clausule
Een USING-clausule noemt kolommen met dezelfde naam die op gelijkheid worden vergeleken en toont elke genoemde gedeelde kolom eenmaal in SELECT *.
USING (customer_id) drukt de koppeling op klantsleutel uit zonder beide kolomverwijzingen uit te schrijven.

V

Veel-op-veelrelatie
Een veel-op-veelrelatie staat toe dat rijen aan beide kanten meerdere tegenhangers hebben en wordt weergegeven met een tabel van gekoppelde paren.
Als één student twee cursussen volgt en één cursus twee studenten telt, legt een tabel enrollments elk student–cursuspaar vast.
Verschil in sleutelnotatie
Een verschil in sleutelnotatie ontstaat als gekoppelde identificatiewaarden verschillende typen of weergaven gebruiken, waardoor het vergelijkingsgedrag van de database afhangt.
De tekst “0042” en het getal 42 kunnen in SQLite door conversie overeenkomen, maar vereisen een consistente behandeling tussen systemen.
Voorspelling van het aantal rijen
Een voorspelling van het aantal rijen schat het resultaat van een join op basis van de koppelingsrelaties en de rijen zonder overeenkomst die het jointype behoudt.
Drie overeenkomende bestellingen plus twee klanten zonder overeenkomst voorspellen vijf rijen voor de left join vanaf klanten.

Over deze les

Door StudeliFout melden

Maak je eigen Studiemateriaal

Maak van je aantekeningen, slides en documenten Leermodules, Oefenvragen, Flashcards en 6 andere tools.

Aan de slag