Uitleg SQL

1. Het SELECT statement (*)

Met het SELECT statement kun je gegevens uit één of meerdere tabellen opvragen.

Hierbij moet je een onderscheid maken tussen het SELECT statement zelf, dat eigenlijk een programma is, en de tabel die als resultaat van het SELECT statement wordt getoond. Deze tabel is virtueel. Dit betekent dat hij niet echt bestaat, maar bij het uitvoeren van het SELECT statement wordt deze opgesteld en bestaat slechts zolang het bijbehorende venster geopend blijft. Wanneer je gegevens in een virtuele tabel tracht te wijzigen, zullen de wijzigingen in werkelijkheid in de onderliggende echte tabellen (tables, ook base tables of reële tabellen genoemd) gewijzigd worden. In veel gevallen is er geen eenduidig verband tussen een rij of kolom uit een virtuele tabel en een rij of kolom uit een reële tabel. In die gevallen zal de virtuele tabel of een deel ervan niet kunnen worden gewijzigd.

In Access wordt een virtuele tabel die het resultaat is van een query een recordset genoemd. Heel vaak kan je hierin de inhoud van enkele of meerdere rijen of kolommen wijzigen. Dan spreekt Access van een dynaset(dynamische verzameling). Soms kan je geen enkele waarde in de resulterende tabel wijzigen. Dan spreekt Access van een snapshot (momentopname).

Hierbij zijn enkele belangrijke opmerkingen nodig:

  • In standaard SQL bestaan zowel het SELECT statement als de virtuele tabel tijdelijk. Je kan daar niet (zoals in Access) het SELECT statement bewaren.
  • In standaard SQL komt een query die je (als programma) bewaart overeen met de definitie van een view. Het gebruikte statement heet dan CREATE VIEW AS (SELECT …). De definitie van de view wordt bewaard. Dit komt (ongeveer) overeen met een bewaarde query in Access. Je kan dus (ongeveer) stellen dat de objecten in het Query tabblad van het Database venster met de definitie van views (virtuele tabellen met een naam) overeenkomen i.p.v. met queries. Queries komen eigenlijk overeen met de definities van virtuele tabellen die je geen naam geeft en niet bewaart, omdat je ze slechts eenmalig nodig hebt. In deze tekst wordt steeds de Access term query i.p.v. view gebruikt.
  • In Access kan je met SQL meerdere soorten Queries opstellen dan met Query By Example. Zo kan je een Union Query, een Pass Through Query en een Data Definition Query enkel in SQL opstellen. Hierop wordt niet verder ingegaan.

Algemeen bevat een SELECT query zes soorten clausules, waarvan de eerste twee steeds voorkomen, en de vier andere kunnen voorkomen:

SELECT fieldlist
FROM tablelist
WHERE condition
GROUP BY group_fieldlist
HAVING group_condition
ORDER BY fieldlist;
  • In de SELECT clause definieer je de kolommen van de virtuele tabel die je wilt opstellen.
  • In de FROM clause geef je aan uit welke tabellen je gegevens komen.
  • In de WHERE clause geef je voorwaarden op waarin je bepaalt welke rijen wel of niet zullen worden getoond.
  • In de GROUP BY clause geef je aan of je rijen wilt groeperen.
  • In de HAVING clause geef je eveneens voorwaarden op, waarin je bepaalt welke rijen wel of niet worden getoond. Deze voorwaarden gelden echter voor gegroepeerde rijen.
  • In de ORDER BY clause geef je de volgorde van de getoonde rijen aan.

1.1 SELECT in één tabel (*)

De eenvoudigste vorm van het SELECT statement haalt de gegevens uit één enkele tabel, die in de FROM clause wordt vermeld.

1.1.1 De SELECT en FROM clauses (*)

De SELECT en FROM clauses zijn steeds de eerste clauses van een SELECT statement.

De syntaxis van de SELECT en FROM clauses is:

SELECT []
    fieldname [AS alias] [, ...]
    FROM tablename

In zijn eenvoudigste vorm SELECT fieldname [, ...] FROM tablename; worden de aangegeven kolommen uit een tabel getoond in de opgegeven volgorde.

Als fieldname mag * worden vermeld. Dit is een korte notatie voor alle velden uit de tabel, in dezelfde volgorde als in de tabel.

 

Fieldname

Hoeft niet noodzakelijk een veld uit een tabel te zijn. Het kan ook een berekend veld zijn zoals prijs*hoeveelheid. In dit laatste geval spreek je beter van een berekende kolom, aangezien deze kolom niet met een veld overeenkomt. De inhoud van een berekende kolom is read-only.

 

 

Je kan elke kolom een andere naam geven door na fieldname AS alias te vermelden. De alias geldt dan als alternatieve kolomnaam. Hij wordt als kolomhoofd getoond. Bij dubbele voorkomende kolommen of kolomnamen moet je een alias opgeven. Bij berekende kolommen hoef je geen alias op te geven, maar je doet dit wel best.

Als fieldname kan een zogenaamde aggregate function worden gebruikt, waarbij totalen voor alle records worden berekend, indien er geen GROUP BY clause is, en totalen per groep, indien er een GROUP BY clause is (zie infra). In standaard SQL zijn er vijf aggregate functions (COUNT – aantal, SUM – totaal, AVG – gemiddelde, MAX – grootste waarde, MIN – kleinste waarde). Access SQL heeft bovendien extra aggregate functions (STDEV – standaardafwijking van de steekproef, VAR – variantie van de steekproef, STDEVP – standaardafwijking van de populatie, VARP – variantie van de populatie). Daarnaast kan je ook berekende totalen opstellen. Per groep wordt één rij getoond. Het resultaat is steeds een snapshot en kan niet worden gewijzigd.

Wanneer een aggregate function wordt gebruikt, moeten alle andere te tonen kolommen

  • ofwel ook een aggregate function zijn;
  • ofwel een groeperingsveld zijn (vermeld in de GROUP BY clause).

Na het sleutelwoord SELECT kan één van de vier sleutelwoorden volgen. Deze hebben de betekenis:

  • Met SELECT ALL (standaard, dus gelijkwaardig met SELECT) toon je alle records, waarbij dubbele rijen worden herhaald.
  • Met SELECT DISTINCT elimineer je dubbele rijen. Elke getoonde rij verschilt van de andere. Hierdoor kan een getoonde rij met meerdere rijen uit de onderliggende tabel overeenkomen, waardoor ze read-only wordt. Het gebruik van het sleutelwoord DISTINCT heeft dus steeds als gevolg dat het resultaat een snapshot is.
  • Met SELECT DISTINCTROW toon je alle rijen, waarvan de onderliggende records van elkaar verschillen. Dubbele rijen worden enkel geëlimineerd wanneer alle veldwaarden uit de onderliggende tabel gelijk zijn. Bij SELECT DISTINCT worden daarentegen rijen geëlimineerd wanneer alle getoonde veldwaarden gelijk zijn. Niet getoonde veldwaarden mogen bij SELECT DISTINCT wel verschillen, bij SELECT DISTINCTROWniet. SELECT DISTINCTROW en SELECT ALL zijn gelijkwaardig wanneer de tabel een primaire sleutel heeft, of wanneer alle rijen in de tabel van elkaar verschillen. SELECT DISTINCTROW komt enkel voor bij Access SQL.
  • Met SELECT TOP n [PERCENT] toon je enkel de eerste n of de eerste % rijen. SELECT TOP is enkel zinvol wanneer de records geordend zijn; er is dus een ORDER BY clause nodig.

Voorbeelden:

Neem aan dat de tabel Klanten de volgende records en velden bevat:

klantnr

(primaire sleutel)

naam gemeente
1 Janssens Brussel
2 Janssens Brussel
3 Peeters Brussel

De hiernavolgende SELECT statements leveren de erbij vermelde recordsets op:

 

  • SELECT ALL naam, gemeente FROM Klanten;

 

 

    • (of

SELECT naam, gemeente FROM klanten;

    ):
naam gemeente
Janssens Brussel
Janssens Brussel
Peeters Brussel

 

  • SELECT DISTINCT naam, gemeente FROM Klanten;

 

    :
naam gemeente
Janssens Brussel
Peeters Brussel

 

  • SELECT DISTINCTROW naam, gemeente FROM Klanten;

 

    :
naam gemeente
Janssens Brussel
Janssens Brussel
Peeters Brussel

 

  • SELECT TOP 2 naam, gemeente FROM Klanten ORDER BY naam;

 

    :
naam gemeente
Janssens Brussel
Janssens Brussel

 

  • SELECT TOP 50 PERCENT naam, gemeente FROM Klanten ORDER BY naam;

 

    :
naam gemeente
Janssens Brussel
Janssens Brussel

In dit laatste geval wordt het getoonde percentage (50% van 3) naar boven afgerond. Bij gelijke waarden voor het ORDER BY veld worden alle gelijk geordende records getoond.

Wanneer de eerste kolom in de tabel ontbreekt, en er dus geen primaire sleutel is, leveren de hiernavolgende SELECT statements de volgende recordsets op:

SELECT ALL naam, gemeente FROM Klanten; (of SELECT naam, gemeente FROM klanten;):

naam gemeente
Janssens Brussel
Janssens Brussel
Peeters Brussel

SELECT DISTINCT naam, gemeente FROM Klanten; :

naam gemeente
Janssens Brussel
Peeters Brussel

SELECT DISTINCTROW naam, gemeente FROM Klanten; :

naam gemeente
Janssens Brussel
Peeters Brussel

In dit laatste geval worden er slechts twee rijen getoond, omdat alle kolommen in de fieldlist voorkomen en er twee identieke rijen zijn.

1.1.2 De WHERE clause (*)

De WHERE clause is niet verplicht in een SELECT statement. Ze wordt gebruikt om via voorwaarden een restrictie op te leggen aan de te tonen records of rijen.

De syntaxis van de WHERE clause is:

WHERE condition

 

 

Hierbij is condition een uitdrukking waarvan de waarde TRUE of FALSE is. Ze wordt opgebouwd met de logische operatoren AND, OR en NOT en de vergelijkingsoperatoren =, <, >, <=, >= en <>. Bovendien kunnen ook wildcards (*, ?, #, [ ] en !) en andere operatoren zoals Like, In en Between voorkomen. Het gebruik van ( ) dient om de volgorde van de evaluatie van de operatoren te bepalen.

De Like operator vergelijkt een tekstuitdrukking in het linkerlid, die een wildcard bevat, met een patroon tussen ” “in het rechterlid. Een patroon is een veralgemeende tekstuitdrukking, d.w.z. een tekst waarin nog enige vrijheid bestaat. Zo staat “A*” voor alle teksten die met een A beginnen, en staat “?end” voor alle teksten van vier tekens waarbij het eerste teken volledig willekeurig is en de laatste drie letterlijk “end” zijn.

De betekenis van de wildcards is als volgt:

* Nul, één of meer willekeurige tekens

? Exact één willekeurig teken

# Exact één willekeurig cijfer

[ ] Een reeks tekens tussen [ ] betekent exact één teken uit de opgegeven reeks. Binnen de [ ] betekent een streepje (-) een bereik van tekens. [A-Za-z] staat dus voor een willekeurige letter. Een uitroepteken betekent een uitsluiting. [!0-9] staat dus voor een willekeurig teken dat geen cijfer is. Wanneer de wildcards als teken worden bedoeld, staan ze tussen [ ].

Voorbeelden (tracht zelf de betekenis uit te zoeken):

SELECT * FROM Studenten
WHERE woonplaats = "Antwerpen";

SELECT * FROM Studenten
WHERE achternaam >="N";

SELECT * FROM Studenten
WHERE achternaam Like [!V]*

SELECT * FROM Studenten
WHERE NOT achternaam Like “V*”

SELECT * FROM Studenten
WHERE postcode Like “[1-3]###”

SELECT * FROM Begeleiders
WHERE vak Like “*[?]*”

SELECT * FROM Studenten
WHERE woonplaats In (“Brussel”, “Gent”, “Leuven”);

SELECT * FROM Studenten
WHERE woonplaats = “Brussel” OR woonplaats = “Gent”
OR woonplaats = “Leuven”;

SELECT * FROM Studenten
WHERE woonplaats = “Brussel” OR achternaam Like “V*”;

SELECT * FROM Studenten
WHERE woonplaats = “Brussel” AND achternaam Like “V*”;

SELECT * FROM Studenten
WHERE geb_datum Between #09/15/72# And #12/31/72#;

SELECT * FROM Studenten
WHERE geb_datum >= #09/15/72# AND geb_datum <= #12/31/72#;

SELECT stagenr, [einde stage] – [begin stage] AS [duur stage]
FROM Studenten
WHERE [begin stage] >=”01/01/72#;

 

 

1.1.3 De ORDER BY clause (*)

De ORDER BY clause is niet verplicht in een SELECT statement. Ze wordt gebruikt om een ordening op te leggen aan de te tonen records of rijen.

De syntaxis van de ORDER BY clause is:

ORDER BY fieldname [][, ...]

 

De getoonde rijen worden geordend op de waarden in de kolommen die worden opgegeven in de ORDER BYclause. Indien er meerdere kolommen zijn, wordt eerst geordend op de eerste kolom, daarna op de volgende enz. Standaard wordt stijdend geordend (0-9 en A-Z). Je kan de volgorde van ordenen wijzigen door na het fieldname ASC (stijgend) of DESC (dalend) te vermelden. Als fieldname moeten veldnamen of uitdrukkingen worden gebruikt, maar geen aliassen!

Wanneer de ORDER BY clause ontbreekt, staat de volgorde van de rijen niet vast.

1.1.4 De GROUP BY clause (*)

De GROUP BY clause is niet verplicht in een SELECT statement. Ze wordt gebruikt wanneer via aggregate functions totalen berekend worden voor groepen records i.p.v. voor alle records samen.

De syntaxis van de GROUP BY clause is:

GROUP BY field [, ...]

 

Een groep bestaat uit alle records met gelijke waarden voor alle velden (of uitdrukkingen) in de GROUP BY clause. Niet in de GROUP BY clause vermelde kolommen die wel in de SELECT clause voorkomen, moeten een aggregate function bevatten.

Voorbeelden:

SELECT Count(*) AS aantal, Avg([einde stage] - [begin stage]) AS [gemiddelde duur] FROM Stages;

SELECT Count(*) AS aantal, Avg([einde stage] - [begin stage]) AS [gemiddelde duur] FROM Stages
GROUP BY instellingsnr;

 

 

In de eerste query wordt het aantal stages en de gemiddelde duur van een stage berekend. De laatste formule is een berekend totaal. Er is één enkele rij.

In de tweede query worden dezelfde berekeningen gemaakt, maar dan opgesplitst per instelling. Er is één rij per instelling.

1.1.5 De HAVING clause (*)

De HAVING clause is niet verplicht in een SELECT statement. Ze wordt gebruikt om via voorwaarden een restrictie op te leggen aan groepen. Dit betekent dat ze in principe enkel samen met de GROUP BY clause voorkomt .

De syntaxis van de HAVING clause is:

HAVING condition

 

Hierbij is condition een uitdrukking waarvan de waarde TRUE of FALSE is. Ze wordt opgebouwd met de logische operatoren AND, OR en NOT en de vergelijkingsoperatoren =, <, >, <=, >= en <>. Verder kunnen wildcards zoals * en ? en andere operatoren zoals Like, In en Between voorkomen. Het gebruik van haakjes ( ) dient om de volgorde van de evaluatie van de operatoren te bepalen.

Het verschil tussen de WHERE en HAVING clauses bestaat er in dat de velden in de condition van de HAVING clause ofwel velden zijn die binnen een groep één waarde aannemen (maar dan kan een WHERE clause worden gebruikt, wat efficiënter is), ofwel aggregate functions bevatten.

Een tweede verschil tussen de WHERE en de HAVING clause betreft het ogenblik waarop de voorwaarde wordt getest. Bij de WHERE clause gebeurt dit voor individuele rijen vóór het groeperen; bij de HAVING clause gebeurt dit voor de groepstotalen na het groeperen.

Aan de hand van enkele voorbeelden wordt hierna het verschil in het gebruik van WHERE en HAVING geïllustreerd. De queries zijn gebaseerd op de volgende tabel Klanten:

naam (primaire sleutel) geslacht woonplaats omzet
Adriaens vrouw Brugge 50 000
Bellens man Brussel 20 000
De Bock vrouw Gent 44 000
De Groot vrouw Brussel 36 000
Mortier man Kortrijk 15 000
Peeters man Brussel 29 000
Rogiers man Gent 97 000
Van den Broecke man Antwerpen 35 000
Willems vrouw Antwerpen 27 000
Wouters man Lier 16 000

 

SELECT woonplaats, Count(*) AS aantal, Sum(omzet) AS [totale omzet] FROM Klanten
WHERE geslacht = "man"
GROUP BY woonplaats
ORDER BY woonplaats;

 

woonplaats aantal totale omzet
Antwerpen 1 35 000
Brussel 2 49 000
Gent 1 97 000
Kortrijk 1 15 000
Lier 1 16 000

SELECT woonplaats, Count(*) AS aantal, Sum(omzet) AS [totale omzet] FROM Klanten
GROUP BY woonplaats
HAVING Count(*)>1
ORDER BY woonplaats;

 

woonplaats aantal totale omzet
Antwerpen 2 62 000
Brussel 3 85 000
Gent 2 141 000

SELECT woonplaats, Count(*) AS aantal, Sum(omzet) AS [totale omzet] FROM Klanten
WHERE woonplaats = "Brussel" OR woonplaats = "Antwerpen"
GROUP BY woonplaats
ORDER BY woonplaats;

SELECT woonplaats, Count(*) AS aantal, Sum(omzet) AS [totale omzet] FROM Klanten
GROUP BY woonplaats
HAVING woonplaats = "Brussel" OR woonplaats = "Antwerpen"
ORDER BY woonplaats;

 

 

woonplaats aantal totale omzet
Antwerpen 2 62 000
Brussel 3 85 000

SELECT woonplaats, Count(*) AS aantal, Sum(omzet) AS [totale omzet] FROM Klanten
WHERE geslacht = "man"
GROUP BY woonplaats
HAVING Count(*)>1
ORDER BY woonplaats;

 

woonplaats aantal totale omzet
Brussel 2 49 000

3.2 SELECT in meerdere tabellen (*)

Naast queries gebaseerd op één tabel zijn er ook queries gebaseerd op meerdere tabellen. Hierbij worden tabellen samengevoegd. Men spreekt dan van een join tussen tabellen. Er zijn drie grote soorten joins:

  • Bij een equi join worden tabellen records uit twee (of meer) tabellen samengevoegd op basis van gelijke waarden tussen één (of meer) velden in beide tabellen. Deze velden zullen dan meestal het zelfde data type, field size en format hebben. Belangrijker is dat zij een zelfde betekenis hebben (een zelfde soort attribuut aanduiden). Het meest voorkomende geval treedt op bij een one to many (of many to one) relatie tussen twee tabellen. De primaire sleutel van de tabel aan de one zijde van de relatie en de vreemde sleutel van de tabel aan de many tabel van de relatie moeten gelijke waarden hebben. Men zal dan meestal beide sleutelvelden dezelfde naam geven (al hoeft dit niet).
  • Bij een theta join wordt een relatie gelegd op basis van een ongelijkheid tussen de waarden van één of meer velden in beide tabellen.
  • Bij een product wordt elke rij van de éne tabel gekoppeld aan elke rij van de andere tabel. Dit komt overeen met het begrip productverzameling uit de relatieleer in de moderne wiskunde. gewoonlijk resulteert dit in een query waarvan de dynaset een zeer groot aantal rijen bevat (het product van het aantal rijen van beide tabellen).

Je kan elk van deze joins aanduiden m.b.v. de FROM en de WHERE clause:

  • In de FROM clause vermeld je de gejoinde tabellen, gescheiden door komma’s.
  • In de WHERE clause neem je de gelijkheid (bij een equi join), de ongelijkheid (bij een theta join) tussen de velden die de relatie bepalen, of helemaal niets (bij een product) op als extra voorwaarde.

Algemene vereenvoudigde syntaxis (de niet relevante clauses worden weggelaten):

 

  • Equi join

 

    :

SELECT fieldlist
FROM table1, table2
WHERE table1.field1 = table2.field2;

 

  • Theta join

 

:

 

 

SELECT fieldlist
FROM table1, table2
WHERE table1.field1 T table2.field2;

 

 

  • Product

 

    :

SELECT fieldlist
FROM table1, table2;

 

Hierbij zijn table1 en table2 de gejoinde tabellen. Field1 en field2 zijn de velden uit resp. table1 en table2 die de relatie bepalen. T is een symbool dat een vergelijkingsoperator verschillend van = aanduidt, bijvoorbeeld kleiner dan (<) of groter dan (>) (Gewoonlijk wordt hier de Griekse hoofdletter Theta voor gebruikt, maar op het world wide web kiezen we de gewone letter T).

Algemeen zullen veldnamen in een query gebaseerd op meer dan één tabel worden voorafgegaan door de naam van de tabel waaruit zij afkomstig zijn en een punt. Wanneer er geen dubbelzinnigheden zijn mag je deze tabelnaam (en het punt) echter weglaten.

In Access SQL en SQL/92 kan bij een equi join de join voorwaarde in de WHERE clause worden vermeld, maar zal ze standaard in de FROM clause worden vermeld. Deze heeft dan de gedaante

SELECT fieldlist
FROM table1 [jointype] JOIN table2
ON table1.field1 = table2.field2;

 

Deze formulering is enkel mogelijk bij een equi join bij een one to many of een one to one relatie. De linkse tabel table1 is dan steeds de tabel aan de one zijde van de one to many relatie en de rechtse tabel table2 de tabel aan de many zijde van de one to many relatie.

Het jointype kan in Access drie waarden aannemen (zie infra).

Wanneer eenmaal tabellen zijn samengevoegd kunnen de WHERE, GROUP BY, HAVING en ORDER BY clauses worden gebruikt zoals bij één tabel queries. In de resulterende dynaset zullen wel sommige gegevens (uit tabellen aan de one zijde van de relatie) herhaald worden getoond, met allerlei gevolgen voor de mogelijkheid tot wijzigen (niet mogelijk of een wijziging in meerdere rijen tegelijk!). Hierop wordt in deze tekst echter niet verder ingegaan.

1.2.1 INNER JOIN (*)

Een inner join bevat enkel records uit beide tabellen waartussen een equi join relatie bestaat. Dit is de standaard join, die wordt aangeduid met de het jointype INNER. Records uit één van beide tabellen die geen corresponderend record hebben in de andere tabel worden niet getoond in de dynaset.

SELECT fieldlist
FROM table1 INNER JOIN table2
ON table1.field1 = table2.field2;

 

Voorbeeld (one to many relatie Studenten – Stagiaires):

SELECT Stagiaires.studentnr, achternaam, voornaam, stagenr, begeleidersnr
FROM Studenten INNER JOIN Stagiares ON Studenten.studentnr = Stagiaires.studentnr;

 

Enkel de namen van de studenten die als stagiares stage lopen worden vermeld, met het nummer van hun stage en van hun begeleider.

1.2.2 LEFT JOIN

Een left outer join bevat alle records uit de tabel table1 aan de one zijde van de relatie en enkel die records uit de tabel table2 aan de many zijde van de relatie waarvoor een corresponderend record in de andere (one) tabel table1 bestaat. Deze join wordt aangeduid met het jointype LEFT. De join wordt een left outer join genoemd omdat de tabel aan de one zijde van de relatie steeds links van de sleutelwoorden LEFT JOIN staat.

SELECT fieldlist
FROM table1 LEFT JOIN table2
ON table1.field1 = table2.field2;

 

Voorbeeld (one to many relatie Studenten – Stagiaires):

SELECT Studenten.studentnr, achternaam, voornaam, stagenr, begeleidersnr
FROM Studenten INNER JOIN Stagiares ON Studenten.studentnr = Stagiaires.studentnr;

 

Alle namen van de studenten worden vermeld, en voor de studenten die stage lopen ook het nummer van hun stage en van hun begeleider.

1.2.3 RIGHT JOIN

Een right outer join bevat alle records uit de tabel table2 aan de many zijde van de relatie en enkel die records uit de tabel table1 aan de one zijde van de relatie waarvoor een corresponderend record in de andere (many) tabel table2 bestaat. Deze join wordt aangeduid met het jointype RIGHT. De join wordt een right outer join genoemd omdat de tabel aan de many zijde van de relatie steeds rechts van de sleutelwoorden RIGHT JOIN staat.

SELECT fieldlist
FROM table1 RIGHT JOIN table2
ON table1.field1 = table2.field2;

 

Voorbeeld (one to many relatie Studenten – Stagiaires):

SELECT Stagiaires.studentnr, achternaam, voornaam, stagenr, begeleidersnr
FROM Studenten RIGHT JOIN Stagiares ON Studenten.studentnr = Stagiaires.studentnr;

 

Alle nummers van stagiaires worden vermeld, met daarbij de nummers van de studenten, stages en begeleiders.

Omdat met elke stagiare (per definitie) een student correspondeert, is het resultaat hetzelfde als bij de inner join. Zoiets gebeurt zeer vaak bij right outer joins.

Right outer joins treden in de praktijk vooral op bij many to many relaties die opgesplitst zijn in een one to manyen een many to one relatie.

Voorbeeld (many to many relatie Studenten – Stagiaires – Begeleiders):

SELECT Studenten.studentnr, Studenten.achternaam, Studenten.voornaam, stagenr, Stagiares.begeleidersnr, Begeleiders.voornaam
FROM Begeleiders RIGHT JOIN (Studenten LEFT JOIN Stagiaires
ON Studenten.studentnr = Stagiaires.studentnr)
ON Begeleiders.begeleidersnr = Stagiaires.begeleidersnr;

 

De plaatsing van de ( ) en de volgorde van de tabellen is steeds zó dat een one tabel steeds links van de gejoinde many tabel (of combinatie) staat:

  • Er is een one to many relatie Studenten – Stagiaires, en alle studenten moeten worden getoond (linkse tabel, dus LEFT JOIN).
  • Er is een one to many relatie Begeleiders – (Studenten-Stagiaires), en alle studenten moeten worden getoond (rechtse tabel, dus RIGHT JOIN).

Het combineren van uitsluitend inner joins onderling is steeds toegelaten. Het combineren van uitsluitend outer joins is steeds toegelaten wanneer de tabel waarvan alle rijen getoond worden een outer join vertoont met alle andere tabellen (dit betekent in de grafische voorstelling van de joins in het Query Design View dat opeenvolgende pijlen nooit naar elkaar toe mogen wijzen). Het combineren van inner en outer joins is echter meestal niet toegelaten. Bij het bewaren of tonen van de dynaset treedt dan steeds een foutmelding op.

Wanneer bij dezelfde many to many relatie alle begeleiders en enkel de studenten met een begeleider moeten worden getoond, neemt het SQL statement de volgende gedaante aan:

SELECT Stagiaires.studentnr, Studenten.achternaam, Studenten.voornaam, Stagiaires.stagenr, Begeleiders.begeleidersnr, Begeleiders.voornaam
FROM Studenten RIGHT JOIN (Begeleiders LEFT JOIN Stagiaires
ON Begeleiders.begeleidersnr = Stagiaires.begeleidersnr)
ON Studenten.studentnr = Stagiaires.studentnr;

http://docent.ehsal.be/vakken/infoburo/Access/SQL.html#_Toc415901451