Modulelessen (4/4)
Een query binnen een andere: subquery's
Je hebt geleerd hoe je kunt extraheren, filteren, groeperen, samenvoegen en transformeren. Daar is nog een laatste fundamenteel idee: een zoekopdracht in een andere plaatsen. Dit zijn worden subquery's genoemd en vormen de stap waarmee u vragen kunt beantwoorden zoals "wie verdient bovengemiddeld?" of "welke afdelingen hebben iemand toegewezen aan een project?".
De basissyntaxis
Een subquery is een SELECT tussen haakjes, gebruikt in plaats van een enkele
waarde of een lijst met waarden in een andere query:
-- Find who earns MORE THAN THE COMPANY AVERAGE:
SELECT first_name, last_name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);De engine voert eerst de subquery uit: SELECT AVG(salary) FROM employees
retourneert een enkel getal — en gebruikt dat getal vervolgens in de buitenste WHERE
alsof je het met de hand hebt geschreven. Dit is precies het voordeel: dat doet u
U hoeft het gemiddelde niet vooraf te weten, SQL berekent het voor u.
De drie meest voorkomende ‘types’
1. Subquery retourneert één enkele waarde
Het bovenstaande voorbeeld: de subquery produceert één rij, één kolom (genaamd
scalair). Je gebruikt het met =, >, < enzovoort.
-- Employee with the highest salary:
SELECT first_name, last_name
FROM employees
WHERE salary = (SELECT MAX(salary) FROM employees);2. Subquery retourneert een lijst
De subquery produceert één kolom, veel rijen. Je gebruikt het met
IN (...):
-- Departments that have at least one employee:
SELECT name
FROM departments
WHERE id IN (SELECT DISTINCT department_id
FROM employees
WHERE department_id IS NOT NULL);3. Subquery als een "tabel" (FROM)
Een subquery kan ook de plaats innemen van een tabel in FROM. Het is nuttig om
bereken aggregaten vooraf en filter ze vervolgens of voeg ze samen:
-- Departments with average salary above 40000:
SELECT d.name, medie.stipendio_medio
FROM departments AS d
JOIN (SELECT department_id, AVG(salary) AS stipendio_medio
FROM employees
GROUP BY department_id) AS medie
ON d.id = medie.department_id
WHERE medie.stipendio_medio > 40000;Subquery of JOIN? Wanneer gebruik je welke
Vaak kan hetzelfde resultaat worden verkregen met een JOIN of met een subquery.
Vuistregel:
- Om rijen van de ene tabel te filteren op basis van een eigenschap van een andere tabel
("werknemers wier afdelingen…"_),
IN (subquery)zijn, is zeer leesbaar. - Gebruik
JOINom kolommen uit meerdere tabellen in het resultaat te combineren. - Om een aggregatie te berekenen en deze als drempel te gebruiken ("boven de gemiddelde"_), is de scalaire subquery de natuurlijke keuze.
In de praktijk zul je beide tegenkomen: de SQL-engine optimaliseert ze vaak op dezelfde manier manier. Kies het formulier dat het beste leest.
Probeer het
Vind de voornaam (voornaam), achternaam (achternaam) en salaris (salaris) van de werknemers die STRIKT meer verdienen dan het bedrijfsgemiddelde. Drie kolommen.
Toon hint
Vervangen ? met de subquery SELECT AVG(salaris) FROM werknemers — retourneert deze een enkel getal dat als drempelwaarde kan worden gebruikt.
Oplossing beschikbaar na 3 pogingen
Oefening beoordelen
Vermeld de naam (departments.name) van afdelingen die ten minste één werknemer hebben met een salaris dat strikt hoger is dan 50.000. Gebruik een subquery met IN. Alfabetisch ordenen.
Toon hint
De binnenste subquery retourneert de ID's van de afdelingen met werknemers met een salaris > 50000. Vervolgens WHERE id IN (...) op de buitenste query.
Oplossing beschikbaar na 3 pogingen