Skip to content
Catégories:

Subs Where Sub Query guide complet pour les utilisateurs avancés

Post date:

Introduction aux sous-requêtes et aux clauses WHERE dans SQL

Vous avez probablement déjà deviné l’opérateur dans une simple requête:

SELECT * FROM clients WHERE ville = 'Lyon';

Mais lorsque vos données deviennent complexes, vous ne pouvez plus simplement les filtrer en un seul appel. Il faut alors explorer sous-requêtes articuler des conditions qui dépendent de résultats intermédiaires. Dans cet article, je vous montre comment maîtriser l’art de combiner la clause avec plusieurs sous-requêtes, correctement imbriquées et efficaces.

Pourquoi la maîtrise des sous-requêtes est cruciale

  1. Analyse croisée : Comparez les valeurs d’une table avec un agrégat d’une autre table.
  2. Sélection dépendante : recherche uniquement les lignes qui satisfont à une condition dépendant d’une autre requête.
  3. Optimisation :évitez les jointures lourdes en filtrant directement à l’aide de sous-requêtes.

Vous êtes désormais prêt à explorer des cas d’utilisation avancés – avec des exemples concrets – pour augmenter votre productivité et la qualité de vos requêtes.

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

1.1. Sous-requêtes scalaires

Une sous-requête qui renvoie une valeur unique.

SELECT nom
FROM fournisseurs
WHERE id = (SELECT id_fournisseur
            FROM commandes
            WHERE numero = 12345);

Ici, la sous-requête renvoie un id_fournisseur unique comme la clause comparer.

1.2. Sous-requêtes avec opérateurs de comparaison

Vous pouvez remplacer l’opérateur = par tout opérateur de comparaison, tel que > ou <.

SELECT produit, prix
FROM catalogue
WHERE prix > (SELECTAVG(prix) FROM catalogue);

Tous les produits dont le prix est supérieur à la moyenne de l’ensemble du catalogue seront retournés.

2. Entrez les sous-requêtes IN, ANY, ALL

2.1. IN

Une sous-requête renvoie une liste de valeurs.

SELECT id_client
FROM clients
WHERE ville IN (SELECT ville FROM villes WHERE population > 100000);

Ici, nous sélectionnons uniquement les clients dont la ville fait partie du sous-ensemble des villes hyperpeuplées.

2.2. ANY / ALL

Ils vous permettent de comparer avec un ensemble de résultats sans transformer la sous-requête.

SELECT produit
FROM catalogue
WHERE prix > ANY (SELECT prix FROM catalogue WHERE collation = 'bonbon');

Votre produit doit être plus cher qu’au moins un bonbon, mais il n’est pas nécessairement plus cher que le meilleur bonbon.

SELECT produit
FROM catalogue
WHERE prix > ALL (SELECT prix FROM catalogue WHERE collation = 'bonbon');

Ici, le produit doit être plus cher que tous doux.

3. Sous-requêtes corrélées : lorsqu’une ligne dépend de la ligne principale

3.1. Exemple classique

Supposons qu’un tableau feuille_de_paie :

SELECT e.nom,
       e.salaire
FROM employe e
WHERE e.salaire > (SELECT AVG(salaire) 
                   FROM employe 
                   WHERE departement = e.departement);

Cette requête affiche les employés qui gagnent plus que le salaire moyen de leur service. La sous-requête est corrélé : fait référence à e.departement.

3.2. Conseil d’optimisation

Dans les bases de données les plus couramment utilisées (PostgreSQL, MySQL, SQL Server), le moteur traite généralement une sous-requête corrélée comme une jointure interne lorsque cela est possible. Si les performances deviennent un problème, considérez:

  • Créez un index sur la colonne utilisée (departement)
  • Utiliser une vue matérialisée qui précalcule la moyenne par département

4. Sous-requêtes imbriquées: lorsque plusieurs niveaux de filtrage sont nécessaires

4.1. Exemple de mosaïque

SELECT p.produit, p.prix
FROM produit p
WHERE p.prix < (   SELECT AVG(prix)
                  FROM produit
                  WHERE type = p.type )
   OR  p.stock > (   SELECT MAX(stock)
                    FROM produit
                    WHERE fournisseur = p.fournisseur );

Dans cet exemple, nous lançons deux sous-requêtes différentes en fonction du type et du fournisseur. On mélange OR et des conditions multiples – le résultat est donc l’intersection de deux filtres.

4.2. Requête plus facile à utiliser

Pour éviter toute surcharge, vous pouvez généraliser en utilisant IN ou des vues temporaires.

SELECT *
FROM produit
WHERE (prix < (SELECT AVG(prix) FROM produit WHERE type = produit.type))
   OR (stock > (SELECT MAX(stock) FROM produit WHERE fournisseur = produit.fournisseur));

Rappel : Dans les bases de leads, la sous-requête corrélée est réévaluée pour chaque ligne (pqm).

5. Choisir un framework d’optimisation: sous-requêtes vs jointure

5.1. Quand privilégier les sous-requêtes

  • Besoin d’un seul agrégat (AVG, MAX, COUNT) par ligne.
  • Étendre la logique métier en un seul modèle.
  • Évitez une jointure qui créerait un grand ensemble de résultats intermédiaires.

5.2. Quand privilégier les articulations

  • Recherchez des informations dans plusieurs tableaux en même temps.
  • Utilisation d’index sur les colonnes associées pour accélérer le filtrage.
  • Réduction de la duplication de travail lorsque le même granulat est réutilisé plus d’une fois.

5.3. Exemple comparatif

Sous-requête

SELECT nom, salaire
FROM employe
WHERE salaire > (SELECT AVG(salaire) FROM employe WHERE departement = 'IT');

Pour rassembler

WITH moyenne AS (
  SELECT departement, AVG(salaire) AS moyenne
  FROM employe
  GROUP BY departement
)
SELECT e.nom, e.salaire
FROM employe e
JOIN moyenne m
  ON e.departement = m.departement
WHERE e.salaire > m.moyenne;

Dans le deuxième exemple, la clause WITH calcule la moyenne une seule fois et permet d’appliquer le filtre sans recalcul.

6. Conseils d’experts avancés

6.1. Pour utiliser LATERAL (SQL:1999) pour la corrélation comme index

Bases de données modernes comme la prise en charge de PostgreSQL LATERAL.

SELECT inv.id,
       inv.quantite,
       v.prix_unitaire
FROM inventaire inv
CROSS JOIN LATERAL (SELECT prix_unitaire FROM prix WHERE produit_id = inv.produit_id LIMIT 1) v;

Cela équivaut à une sous-requête corrélée, mais est plus lisible et efficace.

6.2. Explorer les index de fonctions

Fonctions d’agrégation dans la clause WHERE peut être optimisé à l’aide d’indices de fonction. Dans PostgreSQL, créons un index sur le résultat d’une fonction:

CREATE INDEX idx_categorie_hax_hash
ON produit ((hashlib_sha256(jsonb_build_object('cat', categorie)::text)));

Ensuite, vous pouvez filtrer directement en utilisant le même hachage, en enregistrant le recalcul.

6.3. Gestion des NULL dans les sous-requêtes

NULL C’est un piège courant. Pour utiliser IS NOT NULL ou COALESCE pour garantir le bon fonctionnement de votre logique.

WHERE col_subquery IS NOT NULL

ou

WHERE COALESCE(col_subquery, 0) > 10;

7. Étude de cas: création d’un tableau de bord des ventes

Imaginons que vous deviez créer un tableau de bord avec:

  • LE revenu mensuel par produit.
  • LE pourcentage des ventes parmi les 10% les plus rentables.
WITH ventes AS (
  SELECT produit_id,
         SUM(quantite * prix) AS revenu,
         EXTRACT(YEAR FROM date_vente) AS annee,
         EXTRACT(MONTH FROM date_vente) AS mois
  FROM lignes_vente
  GROUP BY produit_id, annee, mois
),
top10 AS (
  SELECT produit_id
  FROM ventes
  ORDER BY revenu DESC
  LIMIT (SELECT CEIL(COUNT(*) * 0.10) FROM ventes)
)
SELECT v.produit_id,
       v.revenu,
       (v.revenu / (SELECT SUM(v2.revenu) FROM ventes v2 WHERE v2.annee = v.annee AND v2.mois = v.mois)) * 100 AS pourcentage
FROM ventes v
WHERE v.produit_id IN (SELECT produit_id FROM top10)
ORDER BY v.revenu DESC;

Cette requête montre comment combiner WITHsous-requêtes dans SELECT et des agrégations complexes tout en restant lisible.

8. Conclusion: Maîtriser la puissance de la clause WHERE et des sous-requêtes

Les sous-requêtes constituent un moyen puissant de filtrer, comparer et transformer vos données au sein de la clause. . En comprenant les différents types (scalaire, IN, ANY, ALLcorrélées, imbriquées) et sachant quand privilégier une sous-requête ou une jointure, vous pourrez écrire des requêtes plus rapides, plus claires et plus adaptables à des scénarios métiers complexes.

L’essentiel est toujours :

  • Identifiez la logique métier avant de coder.
  • Indices de faveur : fonctions de filtrage, bien positionnées.
  • Profitez des extensions modernes (CROSS JOIN LATERAL, WITH/CTE) pour garder le code lisible et efficace.

Grâce à ces compétences, vous serez désormais prêt à gérer en toute confiance les bases de données les plus exigeantes. Bon SQL!