SQL Pratique
Requêtes imbriquées SQL : corrélées vs jointures expliquées
7 min de lecture

Requêtes imbriquées SQL : corrélées vs jointures expliquées

Maîtrisez les requêtes imbriquées SQL, leurs différences avec les jointures et optimisez vos performances. Guide complet avec exemples pratiques.

Avatar de Thomas LeroyThomas Leroy

Les requêtes imbriquées SQL permettent d'inclure une requête SELECT à l'intérieur d'une autre requête, offrant une alternative puissante aux jointures pour résoudre des problèmes complexes. Comprendre leurs différences avec les jointures et savoir quand les utiliser constitue un savoir-faire essentiel pour tout développeur ou data analyst.

Une requête imbriquée, aussi appelée sous-requête, s'exécute dans le contexte d'une requête principale. Elle peut être corrélée (dépendante de la requête externe) ou non corrélée (indépendante). Cette distinction fondamentale influence directement les performances et la logique de traitement.

Les jointures, quant à elles, combinent les données de plusieurs tables en une seule opération. Bien qu'elles résolvent souvent les mêmes problèmes que les requêtes imbriquées, leur approche diffère radicalement au niveau de l'exécution et des performances.

📌 Ce qu'il faut retenir

  • Les requêtes imbriquées peuvent être corrélées ou non corrélées
  • Les jointures sont généralement plus performantes pour combiner des données
  • Les sous-requêtes corrélées s'exécutent une fois par ligne de la requête externe
  • Le choix entre requête imbriquée et jointure dépend du contexte et des performances

Types de requêtes imbriquées SQL

Requêtes imbriquées non corrélées

Une requête imbriquée non corrélée s'exécute indépendamment de la requête principale. Elle produit un résultat constant utilisé par la requête externe.

SELECT nom, salaire
FROM employes
WHERE salaire > (
    SELECT AVG(salaire)
    FROM employes
);

Cette requête récupère tous les employés dont le salaire dépasse la moyenne. La sous-requête calcule une seule fois la moyenne des salaires.

Requêtes imbriquées corrélées

Une requête corrélée fait référence aux colonnes de la requête externe. Elle s'exécute une fois pour chaque ligne traitée par la requête principale.

SELECT nom, salaire
FROM employes e1
WHERE salaire > (
    SELECT AVG(salaire)
    FROM employes e2
    WHERE e2.departement = e1.departement
);

Ici, la sous-requête calcule la moyenne salariale pour le département de chaque employé traité.

Comparaison avec les jointures

Performance et exécution

Les jointures optimisent généralement mieux les performances grâce aux index et aux algorithmes de jointure avancés. Les sous-requêtes corrélées peuvent devenir coûteuses sur de gros volumes.

Critère Requête imbriquée Jointure
Lisibilité Logique séquentielle claire Peut être complexe
Performance Variable selon le type Généralement optimisée
Utilisation d'index Limitée pour les corrélées Excellente
Colonnes retournées Requête principale uniquement Toutes les tables jointes

Cas d'usage spécifiques

Certaines situations favorisent naturellement l'une ou l'autre approche. Les requêtes imbriquées excellent pour les tests d'existence ou les comparaisons avec des agrégations.

-- Requête imbriquée pour existence
SELECT nom
FROM clients c
WHERE EXISTS (
    SELECT 1
    FROM commandes
    WHERE client_id = c.id
);

-- Équivalent avec jointure
SELECT DISTINCT c.nom
FROM clients c
INNER JOIN commandes cmd ON c.id = cmd.client_id;

Optimisation des requêtes imbriquées

Transformation en jointures

Les optimiseurs SQL modernes transforment automatiquement certaines sous-requêtes en jointures. Comprendre cette transformation aide à écrire du code plus efficace.

-- Sous-requête avec IN
SELECT nom
FROM employes
WHERE departement_id IN (
    SELECT id
    FROM departements
    WHERE budget > 100000
);

-- Transformation automatique en jointure
SELECT e.nom
FROM employes e
INNER JOIN departements d ON e.departement_id = d.id
WHERE d.budget > 100000;

💡 Bon à savoir

L'opérateur EXISTS est souvent plus efficace que IN pour les sous-requêtes, car il s'arrête dès qu'une correspondance est trouvée.

Index et requêtes corrélées

Les index sur les colonnes de corrélation améliorent drastiquement les performances des sous-requêtes corrélées.

-- Index recommandé pour cette corrélation
CREATE INDEX idx_employes_departement ON employes(departement_id);

SELECT nom, salaire
FROM employes e1
WHERE salaire > (
    SELECT AVG(salaire)
    FROM employes e2
    WHERE e2.departement_id = e1.departement_id
);

Techniques avancées avec requêtes imbriquées

Sous-requêtes dans le SELECT

Les requêtes imbriquées peuvent apparaître dans la clause SELECT pour calculer des valeurs dérivées.

SELECT 
    nom,
    salaire,
    (SELECT AVG(salaire) FROM employes) as salaire_moyen,
    salaire - (SELECT AVG(salaire) FROM employes) as ecart_moyenne
FROM employes;

Cette approche reste lisible mais peut impacter les performances si la sous-requête est complexe.

Requêtes imbriquées multiples

Les sous-requêtes peuvent s'imbriquer sur plusieurs niveaux, bien que cela nuise à la lisibilité.

SELECT nom
FROM employes
WHERE departement_id IN (
    SELECT id
    FROM departements
    WHERE manager_id IN (
        SELECT id
        FROM employes
        WHERE anciennete > 10
    )
);

Cas pratiques d'utilisation

Analyse des ventes par région

Comparons l'approche par requête imbriquée et par jointure pour identifier les régions performantes.

-- Avec requête imbriquée
SELECT region
FROM ventes v1
WHERE montant > (
    SELECT AVG(montant) * 1.2
    FROM ventes v2
    WHERE v2.region = v1.region
);

-- Avec jointure et CTE
WITH moyennes_regions AS (
    SELECT region, AVG(montant) * 1.2 as seuil
    FROM ventes
    GROUP BY region
)
SELECT v.region
FROM ventes v
INNER JOIN moyennes_regions mr ON v.region = mr.region
WHERE v.montant > mr.seuil;

La version avec CTE et jointure offre souvent de meilleures performances sur de gros volumes.

⚠️ Attention

Les sous-requêtes corrélées dans des clauses WHERE peuvent créer des performances dégradées sur de grandes tables sans index appropriés.

Détection des doublons

Les requêtes imbriquées excellent pour identifier des enregistrements en double.

SELECT *
FROM clients c1
WHERE EXISTS (
    SELECT 1
    FROM clients c2
    WHERE c2.email = c1.email
    AND c2.id > c1.id
);

Cette requête trouve tous les clients avec des emails en double, en gardant uniquement le premier enregistrement.

Bonnes pratiques et performances

Éviter les requêtes corrélées coûteuses

Les sous-requêtes corrélées dans des boucles peuvent créer des problèmes de performance. Privilégier les jointures ou les fonctions fenêtre quand c'est possible.

-- Éviter cette approche sur de gros volumes
SELECT nom,
    (SELECT COUNT(*) FROM commandes WHERE client_id = c.id) as nb_commandes
FROM clients c;

-- Préférer cette version
SELECT c.nom, COALESCE(cmd.nb_commandes, 0) as nb_commandes
FROM clients c
LEFT JOIN (
    SELECT client_id, COUNT(*) as nb_commandes
    FROM commandes
    GROUP BY client_id
) cmd ON c.id = cmd.client_id;

Tests de performance

Toujours comparer les plans d'exécution entre requêtes imbriquées et jointures sur vos données réelles.

EXPLAIN ANALYZE
SELECT nom FROM employes
WHERE departement_id IN (SELECT id FROM departements WHERE budget > 50000);

EXPLAIN ANALYZE  
SELECT e.nom FROM employes e
INNER JOIN departements d ON e.departement_id = d.id
WHERE d.budget > 50000;

Questions fréquentes

Quand utiliser une requête imbriquée plutôt qu'une jointure ?

Utilisez une requête imbriquée quand vous testez l'existence, comparez avec des agrégations, ou quand la logique séquentielle améliore la lisibilité. Les jointures conviennent mieux pour combiner des colonnes de plusieurs tables ou traiter de gros volumes.

Les requêtes corrélées sont-elles toujours moins performantes ?

Non, sur de petits datasets ou avec des index appropriés, les requêtes corrélées peuvent être efficaces. L'optimiseur SQL peut aussi les transformer automatiquement en jointures. Testez toujours sur vos données réelles.

Comment optimiser une sous-requête lente ?

Créez des index sur les colonnes de corrélation, envisagez la transformation en jointure ou CTE, utilisez EXISTS au lieu de IN quand approprié, et vérifiez le plan d'exécution pour identifier les goulots d'étranglement.

Peut-on imbriquer plusieurs niveaux de sous-requêtes ?

Techniquement oui, mais évitez plus de 2-3 niveaux pour maintenir la lisibilité et les performances. Privilégiez les CTE ou les vues temporaires pour des logiques complexes.

EXISTS vs IN : quelle différence de performance ?

EXISTS s'arrête dès la première correspondance trouvée, tandis qu'IN peut évaluer toute la sous-requête. EXISTS gère aussi mieux les valeurs NULL. Préférez EXISTS pour les tests d'existence simples.

Conclusion

Maîtriser les requêtes imbriquées SQL et leurs différences avec les jointures vous donne la flexibilité nécessaire pour résoudre des problèmes complexes. Chaque approche a ses avantages : les sous-requêtes offrent une logique séquentielle claire, tandis que les jointures optimisent généralement mieux les performances.

Le choix entre requête imbriquée et jointure dépend de votre contexte spécifique, du volume de données et des performances requises. L'important est de tester les deux approches et de comprendre leur comportement sur vos données réelles.

Perfectionnez vos compétences SQL avec nos exercices pratiques et préparez-vous efficacement pour vos entretiens techniques sur SQL Pratique.

Prêt à vous entraîner ?

50 exercices SQL interactifs avec éditeur en ligne, chronomètre et feedback IA.

Voir les exercices