Les sous-requêtes en SQL : quand et comment les utiliser
Une sous-requête est une requête SELECT imbriquée à l'intérieur d'une autre requête. Elle permet de répondre à des questions en plusieurs étapes sans avoir à écrire du code applicatif intermédiaire. Voyons les principales formes.
Sous-requête dans le WHERE
La forme la plus courante : filtrer selon le résultat d'une autre requête.
SELECT nom
FROM clients
WHERE id IN (
SELECT client_id FROM commandes WHERE montant > 100
);
Ici, la sous-requête renvoie d'abord la liste des client_id ayant une commande de plus de 100, puis la requête externe filtre les clients correspondants.
Sous-requête corrélée
Une sous-requête corrélée référence une colonne de la requête externe : elle est donc réévaluée pour chaque ligne.
SELECT c.nom
FROM clients c
WHERE EXISTS (
SELECT 1 FROM commandes co
WHERE co.client_id = c.id AND co.montant > 100
);
Ce style, combiné à EXISTS, est souvent plus performant qu'un IN sur de grandes tables car le moteur peut s'arrêter dès qu'une correspondance est trouvée.
EXISTS à IN quand la sous-requête peut renvoyer beaucoup de lignes ou contenir des NULL — IN se comporte parfois de façon contre-intuitive avec les NULL.Sous-requête dans le FROM
Une sous-requête peut aussi servir de table temporaire, souvent appelée table dérivée.
SELECT ventes_par_client.nom, ventes_par_client.total
FROM (
SELECT c.nom, SUM(co.montant) AS total
FROM clients c
JOIN commandes co ON co.client_id = c.id
GROUP BY c.nom
) AS ventes_par_client
WHERE ventes_par_client.total > 200;
C'est utile quand on doit filtrer ou trier sur un résultat déjà agrégé, puisque WHERE ne peut pas directement utiliser un alias calculé avec SUM.
Sous-requête dans le SELECT
On peut aussi placer une sous-requête scalaire (qui renvoie une seule valeur) directement dans la liste de colonnes.
SELECT
c.nom,
(SELECT COUNT(*) FROM commandes co WHERE co.client_id = c.id) AS nb_commandes
FROM clients c;
Attention : cette forme exécute la sous-requête une fois par ligne de la table externe. Pour de gros volumes, une jointure avec GROUP BY est en général plus performante.
Sous-requête vs jointure : que choisir ?
| Situation | Recommandation |
|---|---|
| Vérifier l'existence d'une correspondance | Sous-requête avec EXISTS |
| Récupérer des colonnes des deux tables | JOIN |
| Filtrer sur un résultat agrégé | Sous-requête dans le FROM, ou HAVING |
| Grandes tables, performance critique | Tester les deux avec EXPLAIN |
