Basis van databases
Uit de tabel Klant (KlantID, Naam) en de tabel Bestelling (BestelID, KlantID, Bedrag) moeten de namen worden opgevraagd van klanten die nog nooit iets hebben besteld. Welk SQL-statement is juist?
- ASELECT Naam FROM Klant WHERE EXISTS (SELECT * FROM Bestelling WHERE Bestelling.KlantID = Klant.KlantID)
- BSELECT Naam FROM Klant WHERE NOT EXISTS (SELECT * FROM Bestelling)
- CSELECT Naam FROM Klant WHERE NOT EXISTS (SELECT * FROM Bestelling WHERE Bestelling.KlantID = Klant.KlantID)
Antwoord en toelichting tonen
Antwoord: C. SELECT Naam FROM Klant WHERE NOT EXISTS (SELECT * FROM Bestelling WHERE Bestelling.KlantID = Klant.KlantID)
EXISTS is een predicaat dat waar is als de subquery tussen haakjes minstens één rij teruggeeft en onwaar als ze er geen teruggeeft; NOT EXISTS is het omgekeerde. Door in de subquery een kolom van de buitenste tabel te gebruiken, zoals in Bestelling.KlantID = Klant.KlantID, wordt het een gecorreleerde subquery die voor elke rij van de buitenste tabel Klant nagaat of die klant bestellingen heeft. In combinatie met NOT EXISTS blijven alleen de klanten zonder enige bestelling over. Met EXISTS krijg je het omgekeerde: de klanten die wel iets hebben besteld. Zonder een voorwaarde die de subquery aan de klant koppelt, geeft de subquery altijd rijen terug zolang de tabel Bestelling minstens één rij heeft, dus is NOT EXISTS altijd onwaar en heeft het resultaat nul rijen. Hetzelfde resultaat is ook te krijgen met een LEFT OUTER JOIN, door de rijen te selecteren waarin de kolommen aan de kant van Bestelling NULL zijn.