🪆sql

Les sous-requetes SQL : imbrication et performance

30 mars 2026 5 min de lecture

Introduction : Pourquoi utiliser des sous-requêtes SQL ?

Salut à toi, futur expert en bases de données ! Si tu maîtrises déjà les bases du SELECT, WHERE et JOIN, il est temps de passer au niveau supérieur avec les sous-requêtes SQL. Imagine une requête dans une requête, comme une poupée russe de données. C'est exactement ça ! Une sous-requête (ou requête imbriquée) est une instruction SQL placée à l'intérieur d'une autre. Elle s'exécute en premier, et son résultat est utilisé par la requête principale. C'est un outil puissant pour répondre à des questions complexes en une seule fois, sans avoir à faire plusieurs requêtes séparées. Par exemple, trouver tous les élèves dont la moyenne est supérieure à la moyenne de la classe, ou lister les produits les plus chers de chaque catégorie. Prêt à plonger dans le monde de l'imbrication ? C'est parti !

Les différents types de sous-requêtes et leur syntaxe

Il existe plusieurs façons d'utiliser une sous-requête, selon l'endroit où tu la places et le type de résultat qu'elle renvoie. Comprendre ces distinctions est crucial pour écrire des requêtes correctes et efficaces.

1. Les sous-requêtes dans la clause WHERE

C'est l'utilisation la plus courante. Tu utilises le résultat d'une sous-requête pour filtrer les lignes de la requête principale.

  • Sous-requête retournant une valeur unique (scalaire) : Utilisée avec les opérateurs de comparaison (=, >, <, >=, <=, <>).
    SELECT nom, prenom FROM eleves WHERE moyenne > (SELECT AVG(moyenne) FROM eleves);
  • Sous-requête retournant une liste de valeurs : Utilisée avec les opérateurs IN ou NOT IN.
    SELECT titre FROM livres WHERE auteur_id IN (SELECT id FROM auteurs WHERE pays = 'France');
  • Sous-requête corrélée : C'est la plus délicate ! La sous-requête dépend de la requête principale. Elle s'exécute une fois pour chaque ligne examinée par la requête externe.
    SELECT e1.nom, e1.prenom FROM eleves e1 WHERE e1.moyenne > (SELECT AVG(e2.moyenne) FROM eleves e2 WHERE e2.classe = e1.classe); Ici, on compare la moyenne de chaque élève à la moyenne de SA classe spécifique.

2. Les sous-requêtes dans la clause SELECT

Ici, la sous-requête agit comme une colonne supplémentaire dans le résultat. Elle doit impérativement retourner une valeur unique (une seule ligne, une seule colonne).
SELECT nom, (SELECT COUNT(*) FROM commandes WHERE commandes.client_id = clients.id) AS nb_commandes FROM clients;

3. Les sous-requêtes dans la clause FROM (Vue dérivée)

Tu peux traiter le résultat d'une sous-requête comme une table temporaire, sur laquelle tu peux ensuite faire un SELECT, un JOIN, etc. C'est très pratique pour structurer des requêtes complexes.
SELECT classe, AVG(moyenne_gen) FROM (SELECT classe, AVG(moyenne) AS moyenne_gen FROM eleves GROUP BY classe) AS stats GROUP BY classe;

Performance : Les pièges à éviter avec les sous-requêtes

Avec un grand pouvoir vient une grande responsabilité ! Les sous-requêtes, surtout si elles sont mal écrites, peuvent ralentir considérablement tes requêtes. Voici les points de vigilance :

  • Les sous-requêtes corrélées sont souvent lentes : Comme elles s'exécutent pour chaque ligne de la table externe, sur de gros volumes de données, les performances peuvent chuter. Il faut toujours se demander si un JOIN ne serait pas plus efficace.
  • Éviter les sous-requêtes inutiles dans le SELECT : Une sous-requête dans le SELECT qui ne dépend pas de la ligne (non corrélée) sera exécutée une fois, ce qui est acceptable. Mais une sous-requête corrélée dans le SELECT se comporte comme une boucle et peut être très coûteuse.
  • Penser à l'indexation : Les colonnes utilisées dans les conditions de jointure entre la requête principale et la sous-requête (surtout les corrélées) doivent être indexées pour accélérer la recherche.
  • Règle d'or : Teste toujours plusieurs formulations (sous-requête vs JOIN) avec EXPLAIN (ou EXPLAIN ANALYZE en PostgreSQL) pour voir quel plan d'exécution le SGBD choisit et lequel est le plus rapide.

Alternatives aux sous-requêtes : JOIN et CTE

Parfois, une sous-requête n'est pas la solution optimale. Heureusement, SQL offre d'autres outils élégants.

1. Utiliser une jointure (JOIN)

Beaucoup de sous-requêtes dans la clause WHERE (surtout avec IN) peuvent être réécrites avec un JOIN, souvent plus performant car optimisé pour les jointures entre tables.
Avec sous-requête : SELECT * FROM produits WHERE categorie_id IN (SELECT id FROM categories WHERE actif = TRUE);
Avec JOIN : SELECT produits.* FROM produits JOIN categories ON produits.categorie_id = categories.id WHERE categories.actif = TRUE;

2. Les Expressions de Table Commune (CTE - WITH)

Introduites dans SQL:1999, les CTE sont une révolution pour la lisibilité. Elles te permettent de définir une ou plusieurs "tables temporaires" nommées au début de ta requête, que tu réutilises ensuite. C'est parfait pour décomposer une requête complexe et remplacer des imbrications profondes.
WITH eleves_bons AS ( SELECT * FROM eleves WHERE moyenne >= 15 ), stats_classes AS ( SELECT classe, COUNT(*) as nb_bons FROM eleves_bons GROUP BY classe ) SELECT * FROM stats_classes WHERE nb_bons > 3;
Les CTE rendent la logique bien plus claire qu'une série de sous-requêtes imbriquées !

Exercice pratique et conclusion

Mettons en pratique : Imagine une base de données d'un lycée avec les tables eleves(id, nom, classe) et notes(id, eleve_id, matiere, note). Écris une requête qui, pour chaque élève, affiche son nom et sa note moyenne, mais seulement si sa moyenne est supérieure à la moyenne générale de tous les élèves.
Essaie de le faire avec une sous-requête corrélée, puis avec une CTE. Compare la lisibilité !

En conclusion, les sous-requêtes SQL sont des alliées précieuses pour interroger tes bases de données avec finesse. Elles te permettent d'exprimer des problèmes complexes de manière souvent intuitive. Cependant, garde toujours un œil sur la performance et n'hésite pas à considérer les JOIN et les CTE comme des alternatives souvent plus efficaces ou plus lisibles. La clé, c'est de maîtriser tous ces outils pour choisir le bon en fonction de la situation. Bonne requête !

📚 Pour aller plus loin

Questions fréquentes

Quelle est la différence entre une sous-requête et un JOIN ?

Une sous-requête est une requête imbriquée à l'intérieur d'une autre, souvent utilisée pour filtrer ou calculer une valeur. Un JOIN combine les lignes de deux tables en fonction d'une condition de relation. Une sous-requête peut souvent être réécrite avec un JOIN (et vice-versa), mais les performances peuvent différer. Les JOIN sont généralement optimisés pour les relations entre tables, tandis que les sous-requêtes corrélées peuvent être plus lentes.

Une sous-requête peut-elle retourner plusieurs colonnes ?

Cela dépend de son utilisation. Dans la clause SELECT, elle doit retourner une seule valeur (une ligne, une colonne). Dans la clause FROM (vue dérivée), elle peut retourner plusieurs colonnes, car son résultat est traité comme une table. Dans la clause WHERE avec l'opérateur IN, elle retourne généralement une seule colonne (une liste de valeurs). Certains SGBD supportent des comparaisons de tuples (ex: WHERE (col1, col2) IN (sous-requête)), mais c'est moins courant.

Comment savoir si ma sous-requête est corrélée ou non ?

Une sous-requête est corrélée si elle fait référence à une colonne de la requête principale (externe). Pour chaque ligne examinée par la requête externe, la sous-requête est réévaluée. Si la sous-requête peut s'exécuter de manière totalement indépendante (sans référence à une table extérieure), elle est non corrélée et ne s'exécute qu'une seule fois. Les sous-requêtes corrélées sont marquées par une dépendance syntaxique (un alias de la table externe utilisé à l'intérieur).

Les CTE (WITH) sont-elles plus performantes que les sous-requêtes ?

Pas nécessairement en termes de vitesse brute. Le SGBD réécrit souvent les CTE et les sous-requêtes de manière similaire. Le grand avantage des CTE est la LISIBILITÉ et la MAINTENABILITÉ du code. Elles permettent de décomposer une requête complexe en étapes logiques nommées, évitant l'enfer des imbrications profondes. Pour la performance, il faut toujours tester avec EXPLAIN. Parfois, une CTE est matérialisée (traité comme une table temporaire), ce qui peut aider ou nuire selon le cas.

Bravo ! Tu as lu cet article
Inscris-toi pour sauvegarder ta progression et gagner des XP
Creer mon compte
sous-requetes SQLSQL avance
Pixel