Leçons du module (4/4)
Une requête dans une autre : sous-requêtes
Vous avez appris à extraire, filtrer, regrouper, joindre et transformer. Là est une dernière idée fondamentale : mettre une requête dans une autre. Ce sont appelées sous-requêtes et elles constituent l'étape qui vous permet de répondre aux questions comme "qui gagne au-dessus de la moyenne ?" ou "quels départements ont quelqu'un affecté à un projet ?".
La syntaxe de base
Une sous-requête est un SELECT entouré de parenthèses, utilisé à la place d'un seul
valeur ou une liste de valeurs dans une autre requête :
-- Find who earns MORE THAN THE COMPANY AVERAGE:
SELECT first_name, last_name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);Le moteur exécute d'abord la sous-requête - SELECT AVG(salary) FROM employees
renvoie un seul numéro - puis utilise ce numéro dans le WHERE externe
comme si vous l'aviez écrit à la main. C'est précisément l'avantage : vous faites
pas besoin de connaître la moyenne à l’avance, SQL la calcule pour vous.
Les trois "types" les plus courants
1. Sous-requête renvoyant une seule valeur
L'exemple ci-dessus : la sous-requête produit une ligne, une colonne (appelée
scalaire). Vous l'utilisez avec =, >, < et ainsi de suite.
-- Employee with the highest salary:
SELECT first_name, last_name
FROM employees
WHERE salary = (SELECT MAX(salary) FROM employees);2. Sous-requête renvoyant une liste
La sous-requête produit une colonne, plusieurs lignes. Vous l'utilisez avec
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. Sous-requête en tant que "table" (FROM)
Une sous-requête peut également remplacer une table dans FROM. Il est utile de
pré-calculez les agrégats, puis filtrez-les ou joignez-les :
-- 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;Sous-requête ou JOIN ? Quand utiliser lequel
Souvent, le même résultat peut être obtenu avec un JOIN ou avec une sous-requête.
Règle générale :
- Pour filtrer les lignes d'une table en fonction d'une propriété d'une autre
("employés dont les services sont…"),
IN (subquery)est très lisible. - Pour combiner des colonnes de plusieurs tables dans le résultat, utilisez
JOIN. - calculer un agrégat et l'utiliser comme seuil (""au-dessus du moyenne"), la sous-requête scalaire est le choix naturel.
En pratique vous verrez les deux : le moteur SQL les optimise souvent de la même manière manière. Choisissez le formulaire qui se lit le mieux.
Essayez-le
Recherchez le prénom (first_name), le nom (last_name) et le salaire (salaire) des employés qui gagnent STRICTEMENT plus que la moyenne de l'entreprise. Trois colonnes.
Afficher l'indice
Remplacer ? avec la sous-requête SELECT AVG(salary) FROM employés — elle renvoie un nombre unique à utiliser comme seuil.
Solution disponible après 3 tentatives
Exercice de révision
Répertoriez le nom (departments.name) des départements qui ont au moins un employé dont le salaire est strictement supérieur à 50 000. Utilisez une sous-requête avec IN. Trier par ordre alphabétique.
Afficher l'indice
La sous-requête interne renvoie les identifiants des départements qui ont des employés avec un salaire > 50 000. Puis WHERE id IN (...) sur la requête externe.
Solution disponible après 3 tentatives