SUBQUERY VISUALIZER

Par :

,le

Visualiseur — Sous-requêtes SQL

Une sous-requête est une requête imbriquée dans une autre. Le moteur l’exécute en premier, puis injecte son résultat dans la requête principale. Choisissez un type de sous-requête et naviguez étape par étape.


        
Cliquez sur un bouton pour avancer ou reculer dans l’exécution.

Le point le plus difficile à assimiler dans les sous-requêtes est leur ordre d’exécution : la sous-requête est traitée avant la requête principale, et non pas de haut en bas comme on lirait du code. L’outil rend cet ordre explicite en forçant l’apprenant à passer par l’étape de la sous-requête avant de voir la table principale filtrée. La distinction visuelle entre le bloc jaune (résultat de la sous-requête) et le bloc bleu (table principale) évite la confusion fréquente entre ce que produit chaque niveau de la requête.

Qu’est ce qu’une sous-requête et pourquoi le moteur l’exécute en premier

Une sous-requête est une instruction SELECT imbriquée à l’intérieur d’une autre requête SQL. Le moteur l’exécute toujours en premier, puis injecte son résultat dans la requête principale comme s’il s’agissait d’une valeur, d’une liste ou d’une table temporaire. Cette priorité d’exécution est le point central que l’outil matérialise : la sous-requête est mise en surbrillance orange à l’étape 1, avant que la requête principale ne soit traitée.

Les sous-requêtes permettent de filtrer des données en fonction d’un calcul dynamique, d’éviter des jointures explicites dans certains cas, ou d’ajouter une colonne calculée directement dans le SELECT. Elles peuvent apparaître dans trois positions syntaxiques : dans la clause WHERE (avec IN ou EXISTS), dans la clause FROM (table dérivée), ou directement dans la liste de colonnes du SELECT (sous-requête scalaire).

Les 4 scénarios et le jeu de données

L’outil utilise deux tables : employes (8 lignes avec idnomdepartementsalaire) et commandes (6 lignes avec idclient_idproduitmontant). La table commandes fait référence aux employés via client_id, ce qui permet de croiser les deux sources selon différentes techniques. Les quatre onglets correspondent aux quatre formes les plus courantes de sous-requêtes en SQL.

-- Table employes (8 lignes)
SELECT * FROM employes;
-- id | nom    | departement | salaire
--  1 | Alice  | Ventes      | 2800
--  2 | Bob    | Tech        | 3500
--  3 | Claire | Ventes      | 3100
--  4 | David  | Interim     | 1800
--  5 | Emma   | Ventes      | 2600
--  6 | Farid  | Interim     | 1900
--  7 | Gaëlle | Tech        | 4000
--  8 | Hugo   | Interim     | 2100

-- Table commandes (6 lignes)
SELECT * FROM commandes;
-- id | client_id | produit | montant
--  1 |     1     | Stylo   | 12
--  2 |     3     | Cahier  | 8
--  3 |     1     | Règle   | 5
--  4 |     7     | Crayon  | 3
--  5 |     3     | Gomme   | 2
--  6 |     2     | Stylo   | 12

Scénario 1 : WHERE IN avec sous-requête

L’onglet WHERE IN (bleu) simule la requête la plus intuitive. La sous-requête SELECT client_id FROM commandes est exécutée en premier et produit la liste [1, 3, 7, 2]. L’outil affiche cette liste dans un bloc jaune à droite, symbolisant son injection dans la requête principale. La table employes est ensuite parcourue : les lignes dont id figure dans cette liste passent en vert, les autres en gris.

WHERE IN est adapté quand la sous-requête retourne un petit ensemble de valeurs distinctes. Sur de très grandes tables, la liste générée par la sous-requête peut être longue et ralentir la comparaison. Dans ce cas, EXISTS ou une jointure sont généralement plus performants.

SELECT nom, salaire
FROM   employes
WHERE  id IN (
    SELECT client_id   -- Exécutée en premier → [1, 3, 7, 2]
    FROM   commandes
);
-- Résultat : Alice (2800), Bob (3500), Claire (3100), Gaëlle (4000)

Scénario 2 : WHERE EXISTS avec sous-requête corrélée

L’onglet WHERE EXISTS (vert) montre la différence fondamentale avec WHERE IN. La sous-requête EXISTS ne produit pas une liste de valeurs : elle teste pour chaque ligne de la table principale si au moins une ligne correspondante existe dans la table secondaire. Dès qu’une correspondance est trouvée, le moteur arrête la recherche pour cette ligne (court-circuit). L’outil explicite ce comportement dans la description de l’étape 2.

La sous-requête corrélée WHERE c.client_id = e.id fait référence à e.id, la ligne courante de la table principale. Elle est réévaluée pour chaque ligne d’employes, contrairement à WHERE IN dont la sous-requête n’est évaluée qu’une seule fois. Ce mécanisme rend EXISTS plus performant lorsque la table secondaire est grande et que l’on recherche simplement une existence, sans avoir besoin des valeurs elles-mêmes.

SELECT nom, salaire
FROM   employes e
WHERE  EXISTS (
    SELECT 1           -- Retourne TRUE dès qu'une ligne correspond
    FROM   commandes c
    WHERE  c.client_id = e.id  -- Corrélée : réévaluée par ligne
);
-- Même résultat que WHERE IN : Alice, Bob, Claire, Gaëlle

Scénario 3 : Sous-requête dans la clause FROM (table dérivée)

L’onglet FROM (sous-req) (violet) illustre un usage plus avancé : la sous-requête génère une table temporaire nommée stats qui est ensuite interrogée comme n’importe quelle table ordinaire. La sous-requête calcule le salaire moyen par département via GROUP BY. L’outil affiche cette table dérivée dans un bloc jaune à l’étape 1, puis montre le filtre WHERE avg_sal > 2500 appliqué sur ses lignes à l’étape 2.

Ce pattern est particulièrement utile pour filtrer sur un résultat agrégé sans recourir à HAVING. Il permet aussi de réutiliser un calcul complexe comme source de données pour plusieurs filtres ou jointures dans la même requête.

SELECT dept, avg_sal
FROM (
    SELECT departement       AS dept,      -- Sous-requête exécutée en premier
           AVG(salaire)      AS avg_sal    -- Produit la table dérivée "stats"
    FROM   employes
    GROUP BY departement
) AS stats
WHERE avg_sal > 2500;
-- Résultat :
-- Ventes | 2833   (moyenne des salaires Alice, Claire, Emma)
-- Tech   | 3750   (moyenne des salaires Bob, Gaëlle)

Scénario 4 : Sous-requête scalaire dans le SELECT

L’onglet Scalaire (orange) montre le cas où la sous-requête retourne une unique valeur numérique — ici AVG(salaire) calculé sur l’ensemble de la table. Cette valeur unique est injectée à deux endroits simultanément : comme colonne calculée dans le SELECT (colonne salaire_moyen répétée sur chaque ligne du résultat), et dans le WHERE pour filtrer les employés dont le salaire dépasse la moyenne.

Une sous-requête scalaire doit impérativement retourner exactement une ligne et une colonne. Si elle retourne plusieurs lignes, le moteur lève une erreur. C’est pourquoi elle contient toujours une fonction d’agrégation (AVGMAXMINCOUNT) ou un filtre garantissant l’unicité du résultat.

SELECT nom,
       salaire,
       (SELECT AVG(salaire) FROM employes) AS salaire_moyen  -- Valeur scalaire
FROM   employes
WHERE  salaire > (SELECT AVG(salaire) FROM employes);        -- Même valeur injectée dans WHERE
-- AVG(salaire) = 2850 (arrondi)
-- Résultat : Bob (3500), Claire (3100), Gaëlle (4000)

Ce que l’outil apporte à la compréhension

Le point le plus difficile à assimiler dans les sous-requêtes est leur ordre d’exécution : la sous-requête est traitée avant la requête principale, et non pas de haut en bas comme on lirait du code. L’outil rend cet ordre explicite en forçant l’apprenant à passer par l’étape de la sous-requête avant de voir la table principale filtrée. La distinction visuelle entre le bloc jaune (résultat de la sous-requête) et le bloc bleu (table principale) évite la confusion fréquente entre ce que produit chaque niveau de la requête.