Cursus
Wanneer we SQL-queries schrijven, volgen we meestal een bepaalde volgorde (SQL staat erom bekend dat het van binnen naar buiten wordt geschreven). De SQL-engines hanteren echter een specifieke uitvoeringsvolgorde bij het compileren van queries, die verschilt van de gebruikelijke schrijfvolgorde. Het begrijpen van de SQL-uitvoeringsvolgorde is belangrijk om query-optimalisatie onder de knie te krijgen, de nauwkeurigheid en prestaties te verbeteren en complexe problemen te debuggen, zoals je zult zien.
Als start raad ik DataCamp’s cursussen Introduction to SQL en de vaardigheidstrack SQL Fundamentals aan om de basis van SQL te leren en hoe je data ophaalt met queries. De SQL Basics Cheat Sheet is een handige gids voor veelgebruikte SQL-functies voor het filteren en aggregeren van data.
Wat is de SQL-uitvoeringsvolgorde?
De SQL-uitvoeringsvolgorde verwijst naar de volgorde waarin de verschillende clausules in de query worden geëvalueerd. Het is de moeite waard om dit te begrijpen, omdat de uitvoeringsvolgorde meestal anders is dan hoe we SQL-queries schrijven. Neem het simpelste voorbeeld: je zou kunnen denken dat bij SELECT * FROM database de SELECT eerst wordt geëvalueerd, maar in werkelijkheid begint de uitvoeringsvolgorde met de FROM-clausule.
Hier is de SQL-uitvoeringsvolgorde. In de volgende sectie lopen we de stappen in detail door.
- FROM/JOIN: Geeft de tabellen op waaruit gegevens worden opgehaald.
- WHERE: Filtert de rijen die aan de voorwaarde voldoen, vóór het groeperen.
- GROUP BY: Groepeert rijen die een eigenschap delen.
- HAVING: Filtert groepen op basis van voorwaarden, toegepast na het groeperen.
- SELECT: Geeft de kolommen op die worden opgehaald of berekend.
- DISTINCT: Verwijdert dubbele rijen uit de resultaatset.
- ORDER BY: Sorteert de resultaatset op opgegeven kolommen.
- LIMIT: Geeft het maximumaantal rijen op dat wordt geretourneerd.
- OFFSET: Geeft op hoeveel rijen worden overgeslagen voordat rijen worden geretourneerd.
In de volgende query heb ik opmerkingen toegevoegd om aan te geven wat eerst wordt geëvalueerd.
-- #6+7 SELECT DISTINCT department_id
-- #1 FROM employees
-- #2 JOIN orders ON customers.customer_id = orders.customer_id
-- #3 WHERE salary > 3000
-- #4 GROUP BY department
-- #5 HAVING AVG(salary) > 5000
-- #8 ORDER BY department
-- #9 LIMIT 10 OFFSET 5
-- #10 OFFSET 5 ROWS FETCH NEXT 10 ROWS ONLY;
Ik heb ook een acrostichon gemaakt dat kan helpen: For Work Goals and Hurdles Search DataCamp's Organized Learning Opportunities.
Fasen van SQL-query-uitvoering
Hoewel de meeste SQL-queries die we schrijven beginnen met de SELECT-instructie, start de logische uitvoeringsvolgorde met de FROM-clausule. Hier schrijf ik queries om de uitvoeringsvolgorde van een query te laten zien. Houd er wel rekening mee dat deze queries onvolledig zijn en niet zullen compileren.
FROM-clausule
SQL-queries beginnen het uitvoeringsproces met de FROM-clausule. Dit is meestal de eerste fase omdat de database de gegevensbronnen/tabellen identificeert. Als meerdere tabellen betrokken zijn, evalueert de SQL-query ook de JOIN-voorwaarde om de tabellen die als gegevensbron zijn opgegeven te combineren.
De onvolledige query hieronder zou eerst gegevens selecteren uit de tabel customers met de FROM-clausule en uit de tabel orders met de JOIN-clausule.
FROM customers
JOIN orders ON customers.customer_id = orders.customer_id;
WHERE-clausule
De WHERE-clausule wordt uitgevoerd na de FROM- en JOIN-clausules om rijen te filteren op basis van specifieke voorwaarden. Let op dat kolommen die met aliassen in de SELECT-clausule zijn gedefinieerd, niet rechtstreeks in de WHERE-clausule kunnen worden gebruikt, aangezien deze vóór SELECT wordt verwerkt.
De onderstaande query gebruikt de WHERE-clausule om records te filteren van werknemers met een bonus groter dan 5000.
FROM employees
JOIN departments ON employees.employee_id = departments.department_id
WHERE salary * 0.1 > 5000;
GROUP BY-clausule
Na het filteren van de rijen voert SQL de GROUP BY-clausule uit om de resultaten te groeperen op basis van opgegeven kolommen. Deze stap wordt meestal gebruikt met aggregatiefuncties zoals COUNT(), SUM() en AVG() om berekeningen uit te voeren op de opgegeven kolommen.
De onderstaande query filtert eerst werknemers met een salary groter dan 3,000, groepeert ze vervolgens op department en berekent het gemiddelde salaris voor elke groep.
FROM employees e
JOIN departments d ON e.employee_id = d.department_id
WHERE e.salary > 3000
GROUP BY e.name, d.department_name;
HAVING-clausule
De HAVING-clausule lijkt op de WHERE-clausule maar wordt gebruikt om gegroepeerde gegevens te filteren na de GROUP BY-bewerking. In de query hieronder groepeert SQL employees per department, berekent het gemiddelde salaris voor elke groep en filtert vervolgens groepen weg waarvan het gemiddelde salaris kleiner dan of gelijk aan 5,000 is.
FROM employees
JOIN departments ON employees.employee_id = departments.department_id
WHERE salary > 3000
GROUP BY department_name
HAVING AVG(salary) > 5000;
SELECT-clausule
In de SELECT-clausule bepaalt SQL de kolommen of expressies die na de voorgaande stappen worden geretourneerd. Je kunt rekenkundige bewerkingen, aliassen en aggregatiefuncties toepassen in de SELECT-clausule.
De volgende query gebruikt de SELECT-clausule om de name en bonus op te halen, berekend als salary * 0.1 uit de tabel employees.
SELECT name, salary * 0.1 AS bonus
FROM employees
JOIN orders ON customers.customer_id = orders.customer_id
WHERE salary > 3000
GROUP BY name
HAVING AVG(salary) > 5000;
DISTINCT-clausule
De DISTINCT-clausule wordt geëvalueerd na de SELECT-clausule in een query. De DISTINCT-clausule is belangrijk bij het verwijderen van dubbele records uit een tabel omdat deze unieke rijen retourneert. De onderstaande query retourneert elke unieke department_id en filtert duplicaten weg.
SELECT DISTINCT department_id
FROM employees
JOIN orders ON customers.customer_id = orders.customer_id
WHERE salary > 3000
GROUP BY department
HAVING AVG(salary) > 5000;
ORDER BY-clausule
De ORDER BY-clausule sorteert de resultaatset op specifieke kolommen of expressies. In tegenstelling tot de WHERE-clausule kan de ORDER BY-clausule kolomaliassen gebruiken die zijn gedefinieerd in de SELECT-instructie.
De onderstaande query sorteert de kolom bonus in aflopende volgorde. Let op dat bonus in de SELECT-instructie is gedefinieerd als alias van een expressie.
SELECT DISTINCT department_id
FROM employees
JOIN orders ON customers.customer_id = orders.customer_id
WHERE salary > 3000
GROUP BY department
HAVING AVG(salary) > 5000
ORDER BY bonus DESC;
LIMIT/OFFSET-clausule
De clausules LIMIT en OFFSET worden meestal als laatste uitgevoerd in een SQL-query om het aantal terug te geven rijen te beperken. De LIMIT-clausule specificeert het maximumaantal rijen dat wordt geretourneerd, en OFFSET geeft op hoeveel rijen worden overgeslagen voordat rijen worden geretourneerd.
De onderstaande query haalt de namen en salarissen van werknemers op, sorteert ze op salary in aflopende volgorde en beperkt de uitvoer tot 10 resultaten, terwijl de eerste 5 rijen worden overgeslagen.
SELECT DISTINCT department_id
FROM employees
JOIN orders ON customers.customer_id = orders.customer_id
WHERE salary > 3000
GROUP BY department
HAVING AVG(salary) > 5000
ORDER BY bonus DESC
LIMIT 10 OFFSET 5;
-- OFFSET 5 ROWS FETCH NEXT 10 ROWS ONLY --SQL SERVER / ORACLE
De clausules LIMIT en OFFSET worden ondersteund in MySQL- en PostgreSQL-databases. Voor SQL Server en Oracle gebruik je OFFSET, ROWS FETCH en ROWS ONLY om het aantal rijen te beperken dat een query retourneert.
Bekijk onze tutorial How to Use SQL OFFSET om meer te leren over paginering van data en database-specifieke ondersteuning voor de clausules OFFSET en LIMIT.
SQL-uitvoeringsvolgorde vs. schrijfvolgorde
SQL is een declaratieve taal, wat betekent dat de uitvoeringsvolgorde van een query verschilt van de schrijfvolgorde. In plaats van te specificeren hoe je een taak uitvoert, geef je aan wat je wilt, en de database-engine bepaalt de beste manier om dat te bereiken. Deze manier verschilt van imperatieve programmeertalen zoals Python of Java, waar je expliciet stap-voor-stap instructies schrijft voor de uitvoering.
Inzicht in de SQL-uitvoeringsvolgorde verandert hoe je nadenkt over het opbouwen van queries. Stel bijvoorbeeld dat je een query schrijft om rijen te filteren op basis van een alias die je in de SELECT-clausule hebt gemaakt:
SELECT price * 0.9 AS discounted_price
FROM products
WHERE discounted_price > 100;
Op het eerste gezicht lijkt dit logisch, maar het zal een fout opleveren. Waarom? Omdat de WHERE-clausule vóór de SELECT-clausule wordt geëvalueerd in de SQL-uitvoeringsvolgorde. Om dit op te lossen, moet je een subquery of HAVING gebruiken:
SELECT price * 0.9 AS discounted_price
FROM products
HAVING discounted_price > 100;
Wil je specifiek meer leren over WHERE en HAVING? Lees dan onze tutorial: The Difference Between WHERE and HAVING in SQL.
Veelgemaakte fouten en best practices
Hoewel de uitvoeringsvolgorde van een query niet wordt beïnvloed door de schrijfvolgorde, is inzicht in de uitvoeringsstroom cruciaal om veelgemaakte fouten te vermijden en de prestaties van queries te verbeteren. De volgende fouten hangen direct samen met een verkeerd begrip van de SQL-uitvoeringsvolgorde:
Veelgemaakte fouten
Dit zijn veelvoorkomende fouten die de prestaties van je query kunnen belemmeren.
-
Kolomaliassen gebruiken in de WHERE-clausule: Omdat de
WHERE-clausule vóór deSELECT-clausule wordt uitgevoerd, zal het gebruik van een alias inWHEREtot een fout leiden. Begrijpen dat SQLWHEREvóórSELECTevalueert, leert je dat je de volledige expressie moet herhalen in plaats van te vertrouwen op een alias. -
HAVING gebruiken voor rijfiltering in plaats van WHERE: De
HAVING-clausule wordt uitgevoerd naGROUP BYen is bedoeld voor het filteren van geaggregeerde gegevens. Als je niet-geaggregeerde gegevens filtert, hoort dat in de WHERE-clausule. Weten wat het verschil in uitvoeringsvolgorde is tussen WHERE en HAVING helpt je bepalen waar elke voorwaarde thuishoort. -
Onjuist gebruik van aggregaties in SELECT zonder GROUP BY: Omdat
GROUP BYwordt uitgevoerd vóórHAVINGofSELECT, leidt het niet groeperen van je data voordat je een aggregatiefunctie toepast tot onjuiste resultaten of fouten. Inzicht in de uitvoeringsvolgorde maakt duidelijk waarom deze twee clausules samen moeten gaan. -
Aliassen niet goed gebruiken in de ORDER BY-clausule: In tegenstelling tot de
WHERE-clausule wordt deORDER BY-clausule geëvalueerd naSELECT. Hierdoor kun je voor het sorteren aliassen gebruiken die inSELECTzijn aangemaakt, wat verwarring voorkomt doordat je weet wanneer aliassen beschikbaar zijn.
Best practices
Houd rekening met de volgende best practices om ervoor te zorgen dat je queries naar verwachting worden uitgevoerd.
-
Filter vroeg met WHERE: Omdat de
WHERE-clausule vóórGROUP BYenJOINwordt uitgevoerd, verkleint vroeg filteren het aantal rijen dat door volgende clausules wordt verwerkt, wat de prestaties verbetert. Door niet-geaggregeerde data zo vroeg mogelijk te filteren, beperk je de data die gegroepeerd of gejoint moet worden, wat verwerkingstijd bespaart. -
Pre-aggregeer data vóór joins: Omdat
FROMenJOINde eerste uitgevoerde clausules zijn, kun je met subqueries of common table expressions (CTE’s) vooraf aggregeren om de dataset te verkleinen vóór het join-proces. Zo worden tijdens de join minder rijen verwerkt. -
Optimaliseer ORDER BY met indexen: Omdat de
ORDER BY-clausule een van de laatste stappen is, versnelt het indexeren van de gesorteerde kolommen de prestaties doordat de database sorteertaken efficiënter kan afhandelen. -
Vermijd SELECT * in productiequeries: De
SELECT-clausule wordt uitgevoerd na filteren, groeperen en aggregeren, dus door alleen de benodigde kolommen te specificeren, minimaliseer je de hoeveelheid opgehaalde data en verminder je onnodige overhead.
Conclusie
Inzicht in de SQL-uitvoeringsvolgorde is belangrijk voor het schrijven van efficiënte, nauwkeurige en geoptimaliseerde queries. We hebben de logische volgorde van query-uitvoering in SQL besproken en vergeleken met de schrijfvolgorde. Ik moedig je aan om verschillende queries te schrijven om de logische uitvoeringsvolgorde beter te begrijpen. Het beheersen van dit concept zal je vermogen om SQL-queries te troubleshooten en te optimaliseren sterk verbeteren.
Als je je SQL-vaardigheden wilt uitbreiden, raad ik DataCamp’s Associate Data Analyst in SQL-carrièretrack aan om een vaardige data-analist te worden. De cursus Reporting in SQL helpt je ook bij het bouwen van complexe rapporten en dashboards voor effectieve datavisualisatie. Tot slot kun je de SQL Associate Certification behalen om je vaardigheid in het gebruik van SQL voor bedrijfsproblemen te laten zien en je te onderscheiden van andere professionals.
SQL-uitvoeringsvolgorde: veelgestelde vragen
Hoe verschilt de SQL-uitvoering van de schrijfvolgorde?
De SQL-uitvoeringsvolgorde begint meestal met de FROM-clausule, gevolgd door clausules zoals WHERE en GROUP BY, terwijl de schrijfvolgorde start met de SELECT-instructie.
Hoe past JOIN in de uitvoeringsvolgorde?
De JOIN-operaties worden uitgevoerd als onderdeel van de FROM-clausule.
Kan ik kolomaliassen gebruiken in de WHERE-clausule?
Nee, kolomaliassen worden gedefinieerd in de SELECT-clausule, die na de WHERE-clausule wordt uitgevoerd.
Wat is het verschil tussen WHERE en HAVING?
WHERE filtert rijen vóór het groeperen, terwijl HAVING filtert na GROUP BY en werkt op geaggregeerde data.
Heeft de SQL-uitvoeringsvolgorde invloed op de prestaties van queries?
Ja, inzicht in de uitvoeringsvolgorde stelt je in staat om queries te optimaliseren door vroeg te filteren en onnodige bewerkingen te verminderen.

