Bij een SQL-join voert u een query uit die meerdere tabellen samenvoegt.
Deze zelfstudie over SQL-joins geeft basisvoorbeelden van SQL-joins, evenals een inleiding tot de verschillende typen joins.
SQL-deelnametypes
De ANSI SQL-standaard specificeert vijf typen joins, zoals vermeld in de volgende tabel.
Aanmeldtype | Beschrijving |
---|---|
INNER JOIN | Retourneert rijen als er in beide tabellen ten minste één rij is die overeenkomt met de voorwaarde voor samenvoegen. |
LEFT OUTER JOIN of LEFT JOIN | Retourneert rijen met gegevens in de linkertabel (links van de JOIN zoekwoord), zelfs als er geen overeenkomende rijen in de juiste tabel staan. |
RIGHT OUTER JOIN of RIGHT JOIN | Retourneert rijen met gegevens in de rechtertabel (rechts van de JOIN zoekwoord), zelfs als er geen overeenkomende rijen in de linkertabel zijn. |
FULL OUTER JOIN of FULL JOIN | Retourneert alle rijen, zolang er overeenkomende gegevens in een van de tabellen zijn. |
CROSS JOIN | Retourneert rijen die elke rij uit de eerste tabel combineren met elke rij uit de tweede tabel. |
Er zijn ook andere termen voor verschillende samenvoegbewerkingen, zoals de volgende:
Deelnemen | Beschrijving |
---|---|
Zelf lid worden | Als een tafel zich bij zichzelf voegt. |
Natuurlijke deelname | Een impliciete join gebaseerd op de gemeenschappelijke kolommen in de twee tabellen die worden samengevoegd. |
Equi-join | Een join die alleen gelijkheidsvergelijkingen bevat in het join-predikaat. |
SQL Join-syntaxis
Innerlijke joins kunnen worden opgegeven in de FROM
of WHERE
clausules. Outer-joins en cross-joins kunnen worden gespecificeerd in de FROM
alleen clausule.
Een SQL-join maken in de FROM
clausule, doe zoiets als dit:
SELECT *
FROM Table1 < JoinType > Table2 [ ON ( JoinCondition ) ]
Waar JoinType
specificeert wat voor soort join wordt uitgevoerd, en JoinCondition
definieert het predikaat dat moet worden geëvalueerd voor elk paar samengevoegde rijen.
Een join specificeren in de WHERE
clausule, doe zoiets als dit:
SELECT *
FROM Table1, Table2 [ WHERE ( JoinCondition ) ]
Nogmaals, JoinCondition
definieert het predikaat dat moet worden geëvalueerd voor elk paar samengevoegde rijen.
Ook alles tussen vierkante haken ([]
) is optioneel.
Voorbeeldtabellen voor de voorbeelden in deze zelfstudie
De meeste voorbeelden in deze tutorial voeren samenvoegingen uit tegen de volgende twee tabellen.
De PetTypes
tafel:
+-------------+-----------+ | PetTypeId | PetType | |-------------+-----------| | 1 | Bird | | 2 | Cat | | 3 | Dog | | 4 | Rabbit | +-------------+-----------+ (4 rows affected)
De Pets
tafel:
+---------+-------------+-----------+-----------+------------+ | PetId | PetTypeId | OwnerId | PetName | DOB | |---------+-------------+-----------+-----------+------------| | 1 | 2 | 3 | Fluffy | 2020-11-20 | | 2 | 3 | 3 | Fetch | 2019-08-16 | | 3 | 2 | 2 | Scratch | 2018-10-01 | | 4 | 3 | 3 | Wag | 2020-03-15 | | 5 | 1 | 1 | Tweet | 2020-11-28 | | 6 | 3 | 4 | Fluffy | 2020-09-17 | | 7 | 3 | 2 | Bark | NULL | | 8 | 2 | 4 | Meow | NULL | +---------+-------------+-----------+-----------+------------+ (8 rows affected)
De innerlijke verbinding
De SQL INNER JOIN
retourneert rijen wanneer er in beide tabellen ten minste één rij is die overeenkomt met de join-voorwaarde.
SELECT
Pets.PetName,
PetTypes.PetType
FROM Pets
INNER JOIN PetTypes
ON Pets.PetTypeId = PetTypes.PetTypeId;
Resultaat:
-----------+-----------+ | PetName | PetType | |-----------+-----------| | Fluffy | Cat | | Fetch | Dog | | Scratch | Cat | | Wag | Dog | | Tweet | Bird | | Fluffy | Dog | | Bark | Dog | | Meow | Cat | +-----------+-----------+ (8 rows affected)
Een inner join specificeren in de FROM
clausule gebruiken we INNER JOIN
. We gebruiken ook de ON
trefwoord om het predikaat te definiëren dat moet worden geëvalueerd voor elk paar samengevoegde rijen.
Ongeacht het type join, kwalificeren we onze kolomnamen met de tabelnamen. De reden dat we dit doen is om onduidelijkheid over de kolomnamen tussen de tabellen te voorkomen. Beide tabellen kunnen kolommen met dezelfde naam hebben (zoals in ons voorbeeld), en in dergelijke gevallen weet het DBMS niet naar welke kolom u verwijst. Door de kolomnamen vooraf te laten gaan door hun tabelnamen zorgt u ervoor dat u naar de juiste kolom verwijst en voorkomt u fouten die zouden kunnen voortvloeien uit onduidelijkheid over de kolom waarnaar u verwijst.
In dit voorbeeld hebben beide tabellen een PetTypeId
kolom. De Pets.PetTypeId
kolom is een refererende sleutel voor de PetTypes.PetTypeId
kolom, wat de primaire sleutel is voor die tabel.
In dit voorbeeld kunnen we zien dat alle huisdieren worden geretourneerd, maar niet alle soorten huisdieren. Er zijn geen konijnen in de Pets
tabel, en dus de Rabbits
huisdiertype wordt niet geretourneerd.
De reden waarom de Rabbits
type niet wordt geretourneerd, is omdat de INNER JOIN
retourneert alleen rijen als er in beide tabellen ten minste één rij is die overeenkomt met de join-voorwaarde. In dit geval, Rabbits
staat slechts in één tabel (de PetTypes
tafel).
Houd er rekening mee dat het join-type optioneel is. Daarom kunt u bij de meeste (zo niet alle) DBMS'en de INNER
. weglaten trefwoord. Wanneer u dit weglaat (d.w.z. alleen JOIN
specificeren) ), wordt aangenomen dat het een inner join is.
Daarom zouden we het bovenstaande voorbeeld hiernaar kunnen herschrijven:
SELECT
Pets.PetName,
PetTypes.PetType
FROM Pets
JOIN PetTypes
ON Pets.PetTypeId = PetTypes.PetTypeId;
Ook, zoals bij elke SQL-instructie, is de FROM
clausule kan op één hele regel staan als je dat liever hebt:
SELECT
Pets.PetName,
PetTypes.PetType
FROM Pets JOIN PetTypes ON Pets.PetTypeId = PetTypes.PetTypeId;
Aliasen
Het is gebruikelijk om tabelaliassen te gebruiken bij het uitvoeren van SQL-joins. Aliassen helpen om de code beknopter en gemakkelijker te lezen te maken.
Daarom zouden we het vorige voorbeeld in dit kunnen veranderen:
SELECT
p.PetName,
pt.PetType
FROM Pets p INNER JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId;
Resultaat:
-----------+-----------+ | PetName | PetType | |-----------+-----------| | Fluffy | Cat | | Fetch | Dog | | Scratch | Cat | | Wag | Dog | | Tweet | Bird | | Fluffy | Dog | | Bark | Dog | | Meow | Cat | +-----------+-----------+ (8 rows affected)
De Equi-Join
De bovenstaande join kan ook worden aangeduid als een equi-join . Een equi-join is een join die alleen gelijkheidsvergelijkingen bevat in het join-predikaat.
Een andere manier om de bovenstaande join te schrijven is als volgt:
SELECT
p.PetName,
pt.PetType
FROM
Pets p,
PetTypes pt
WHERE p.PetTypeId = pt.PetTypeId;
Resultaat:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Fluffy | Cat | | Fetch | Dog | | Scratch | Cat | | Wag | Dog | | Tweet | Bird | | Fluffy | Dog | | Bark | Dog | | Meow | Cat | +-----------+-----------+
Dit is een voorbeeld van het specificeren van een inner join in de WHERE
clausule. We hebben gewoon een door komma's gescheiden lijst van de tabellen gegeven en vervolgens een WHERE
voorwaarde. Als we de WHERE
. hadden weggelaten voorwaarde, zouden we zijn geëindigd met een CROSS JOIN
.
Veel beginners vinden de bovenstaande syntaxis veel gemakkelijker te begrijpen dan de INNER JOIN
syntaxis. Voel je vrij om deze syntaxis te gebruiken als je dat liever hebt, maar houd er rekening mee dat de meeste SQL-professionals de voorkeur geven aan de INNER JOIN
syntaxis van het vorige voorbeeld.
Zie SQL Inner Join voor meer voorbeelden, waaronder een inner join die 3 tabellen samenvoegt.
De juiste deelname
Ook bekend als de RIGHT OUTER JOIN
, de RIGHT JOIN
retourneert rijen met gegevens in de juiste tabel (rechts van de JOIN
zoekwoord), zelfs als er geen overeenkomende rijen in de linkertabel zijn.
SELECT
p.PetName,
pt.PetType
FROM Pets p
RIGHT JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId;
Resultaat:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Tweet | Bird | | Fluffy | Cat | | Scratch | Cat | | Meow | Cat | | Fetch | Dog | | Wag | Dog | | Fluffy | Dog | | Bark | Dog | | NULL | Rabbit | +-----------+-----------+ (9 rows affected)
In dit geval kregen we een extra PetType
waarde – Rabbit
– ook al is er geen huisdier in de Pets
tafel van dat type. Dit resulteert in een NULL
waarde in de PetName
kolom tegen Rabbit
.
Zie SQL Right Join voor meer voorbeelden, waaronder een Right Join die 3 tabellen samenvoegt.
The Left Join
Ook bekend als de LEFT OUTER JOIN
, de SQL LEFT JOIN
retourneert rijen met gegevens in de linkertabel (links van de JOIN
zoekwoord), zelfs als er geen overeenkomende rijen in de juiste tabel staan.
Dit is het tegenovergestelde van de RIGHT JOIN
.
Als we het vorige voorbeeld wijzigen om een left join te gebruiken, krijgen we het volgende resultaat.
SELECT
p.PetName,
pt.PetType
FROM Pets p
LEFT JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId;
Resultaat:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Fluffy | Cat | | Fetch | Dog | | Scratch | Cat | | Wag | Dog | | Tweet | Bird | | Fluffy | Dog | | Bark | Dog | | Meow | Cat | +-----------+-----------+ (8 rows affected)
In dit specifieke geval zijn onze resultaten hetzelfde als bij de inner join.
Als we echter de tafelvolgorde omwisselen in onze FROM
clausule, krijgen we een vergelijkbaar resultaat als de juiste join in het vorige voorbeeld.
SELECT
p.PetName,
pt.PetType
FROM PetTypes pt
LEFT JOIN Pets p
ON p.PetTypeId = pt.PetTypeId;
Resultaat:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Tweet | Bird | | Fluffy | Cat | | Scratch | Cat | | Meow | Cat | | Fetch | Dog | | Wag | Dog | | Fluffy | Dog | | Bark | Dog | | NULL | Rabbit | +-----------+-----------+ (9 rows affected)
U kunt dus zien dat elk resulterend verschil tussen de linker en rechter joins uitsluitend afhangt van de volgorde van de kolommen in de FROM
clausule.
Zie SQL Left Join voor meer voorbeelden, waaronder een left join die 3 tabellen samenvoegt.
De volledige deelname
De SQL FULL JOIN
(of FULL OUTER JOIN
) geeft alle rijen terug, zolang er overeenkomende gegevens in een van de tabellen zijn.
Met andere woorden, het is alsof je zowel een linker- als een rechterjoin in één join hebt.
Hier is een voorbeeld van een volledige deelname.
SELECT
p.PetName,
pt.PetType
FROM Pets p
FULL JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId;
Resultaat:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Fluffy | Cat | | Fetch | Dog | | Scratch | Cat | | Wag | Dog | | Tweet | Bird | | Fluffy | Dog | | Bark | Dog | | Meow | Cat | | NULL | Rabbit | +-----------+-----------+ (9 rows affected)
Dit geeft hetzelfde resultaat als met de rechter join, maar het zou een ander resultaat hebben opgeleverd als er een rij in de linkertabel was geweest die geen overeenkomstige waarde had in de rechtertabel.
Laten we de tabelnamen omwisselen en het opnieuw uitvoeren.
SELECT
p.PetName,
pt.PetType
FROM PetTypes pt
FULL JOIN Pets p
ON p.PetTypeId = pt.PetTypeId;
Resultaat:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Tweet | Bird | | Fluffy | Cat | | Scratch | Cat | | Meow | Cat | | Fetch | Dog | | Wag | Dog | | Fluffy | Dog | | Bark | Dog | | NULL | Rabbit | +-----------+-----------+ (9 rows affected)
Zelfde resultaat.
Zie SQL Full Join voor meer voorbeelden, waaronder een volledige join die 3 tabellen samenvoegt.
The Cross Join
De SQL CROSS JOIN
retourneert rijen die elke rij uit de eerste tabel combineren met elke rij uit de tweede tabel.
Met andere woorden, het retourneert het Cartesiaanse product van rijen uit tabellen in de join.
SELECT
p.PetName,
pt.PetType
FROM Pets p
CROSS JOIN PetTypes pt;
Resultaat:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Fluffy | Bird | | Fetch | Bird | | Scratch | Bird | | Wag | Bird | | Tweet | Bird | | Fluffy | Bird | | Bark | Bird | | Meow | Bird | | Fluffy | Cat | | Fetch | Cat | | Scratch | Cat | | Wag | Cat | | Tweet | Cat | | Fluffy | Cat | | Bark | Cat | | Meow | Cat | | Fluffy | Dog | | Fetch | Dog | | Scratch | Dog | | Wag | Dog | | Tweet | Dog | | Fluffy | Dog | | Bark | Dog | | Meow | Dog | | Fluffy | Rabbit | | Fetch | Rabbit | | Scratch | Rabbit | | Wag | Rabbit | | Tweet | Rabbit | | Fluffy | Rabbit | | Bark | Rabbit | | Meow | Rabbit | +-----------+-----------+ (32 rows affected)
Zoals je je waarschijnlijk kunt voorstellen, kan dit erg gevaarlijk zijn als je het tegen de verkeerde tafels uitvoert.
Het is hetzelfde als dit doen:
SELECT
p.PetName,
pt.PetType
FROM Pets p, PetTypes pt;
U kunt een WHERE
. toevoegen clausule toe aan een cross join, waardoor het een inner join wordt.
Zoals dit:
SELECT
p.PetName,
pt.PetType
FROM Pets p
CROSS JOIN PetTypes pt
WHERE p.PetTypeId = pt.PetTypeId;
Resultaat:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Fluffy | Cat | | Fetch | Dog | | Scratch | Cat | | Wag | Dog | | Tweet | Bird | | Fluffy | Dog | | Bark | Dog | | Meow | Cat | +-----------+-----------+ (8 rows affected)
Zie SQL Cross Join voor meer voorbeelden.
The Natural Join
De SQL NATURAL JOIN
is een type equi-join waarbij het join-predikaat impliciet ontstaat door alle kolommen in beide tabellen met dezelfde kolomnaam in de samengevoegde tabellen te vergelijken.
De resultatenset bevat slechts één kolom voor elk paar gelijknamige kolommen. Als er geen kolommen met dezelfde namen worden gevonden, is het resultaat een cross join.
SELECT
Pets.PetName,
PetTypes.PetType
FROM Pets NATURAL JOIN PetTypes;
Resultaat:
petname | pettype ---------+--------- Fluffy | Cat Fetch | Dog Scratch | Cat Wag | Dog Tweet | Bird Fluffy | Dog Bark | Dog Meow | Cat (8 rows)
Eigenlijk is de natuurlijke join niet echt een join-type, zoals wordt overwogen door de ANSI-standaard. Het is een trefwoord dat u optioneel kunt invoegen om van de join een natuurlijke join te maken.
Daarom zouden we het bovenstaande voorbeeld kunnen veranderen in NATURAL INNER JOIN
als we wilden:
SELECT
Pets.PetName,
PetTypes.PetType
FROM Pets NATURAL INNER JOIN PetTypes;
Zoals eerder vermeld, zijn inner joins het standaard jointype, dus als u het jointype weglaat (bijv. INNER
, LEFT
, RIGHT
, etc), dan wordt het behandeld als een inner join.
Als de opmaak van deze resultaten er anders uitziet dan de vorige resultaten, komt dat omdat ik naar PostgreSQL moest springen om deze query uit te voeren. Ik heb de vorige voorbeelden in SQL Server uitgevoerd, maar SQL Server ondersteunt de natuurlijke join niet.
Zie SQL Natural Join voor meer voorbeelden, waaronder een natuurlijke join die 3 tabellen samenvoegt.
The Self Join
De SQL SELF JOIN
voegt zich bij een tafel bij zichzelf.
Een klassiek voorbeeld van een self-join is in een Employees-tabel. In zo'n tabel kan de ene medewerker zich melden bij een andere medewerker. Daarom kunt u een self-join gebruiken om deel te nemen aan de tabel in de kolom met werknemers-ID's en kolom met manager-ID's.
Stel dat we de volgende tabel hebben:
+--------------+-------------+------------+-------------+ | EmployeeId | FirstName | LastName | ReportsTo | |--------------+-------------+------------+-------------| | 1 | Homer | Connery | NULL | | 2 | Bart | Pitt | 1 | | 3 | Maggie | Griffin | 1 | | 4 | Peter | Farnsworth | 2 | | 5 | Marge | Morrison | NULL | | 6 | Lisa | Batch | 5 | | 7 | Dave | Zuckerberg | 6 | | 8 | Vlad | Cook | 7 | +--------------+-------------+------------+-------------+
We kunnen een self-join doen op deze tafel om alle medewerkers en hun managers terug te sturen.
SELECT
CONCAT(e1.FirstName, ' ', e1.LastName) AS Employee,
CONCAT(e2.FirstName, ' ', e2.LastName) AS Manager
FROM Employees e1
LEFT JOIN Employees e2
ON e1.ReportsTo = e2.EmployeeId;
Resultaat:
+------------------+-----------------+ | Employee | Manager | |------------------+-----------------| | Homer Connery | | | Bart Pitt | Homer Connery | | Maggie Griffin | Homer Connery | | Peter Farnsworth | Bart Pitt | | Marge Morrison | | | Lisa Batch | Marge Morrison | | Dave Zuckerberg | Lisa Batch | | Vlad Cook | Dave Zuckerberg | +------------------+-----------------+
Zie SQL Self Join voor meer voorbeelden.