Les sous-requêtes en SQL

23 Sep 2019 23 Sep 2019 19828 vues ESSADDOUKI Mostafa 9 min de lecture

Les sous-requêtes en SQL

Définition

Une sous-requête, également appelée requête imbriquée ou sous-sélection, est une requête SELECT intégrée à la clause WHERE ou HAVING d'une autre requête SQL.

Les données renvoyées par la sous-requête sont utilisées par l'instruction externe de la même manière qu'une valeur littérale serait utilisée.

Utilité

Les sous-requêtes constituent un moyen simple et efficace de gérer les requêtes qui dépendent des résultats d'une autre requête.

Règles importantes

  • Une sous-requête doit toujours apparaître entre parenthèses.
  • Une sous-requête doit renvoyer une seule colonne (sauf pour la comparaison de lignes).
  • Pour renvoyer plusieurs lignes, utiliser des opérateurs comme IN ou NOT IN.
  • Une clause ORDER BY ne peut pas être utilisée dans une sous-requête (utiliser GROUP BY si nécessaire).
  • Une sous-requête ne peut pas être une UNION (une seule SELECT est autorisée).

Les sous-requêtes sont le plus souvent utilisées avec l'instruction SELECT. Toutefois, vous pouvez également les utiliser dans une instruction INSERT, UPDATE ou DELETE ou dans une autre sous-requête.

Tables d'exemple

Pendant ce cours, nous allons travailler sur ces 4 tables :

Table - Departement

+--------+--------------+
| Id_dep | Nom_dep      |
+--------+--------------+
|      1 | Informatique |
|      2 | RH           |
|      3 | Vente        |
|      4 | Strategies   |
+--------+--------------+

Table - Employes

+----+---------+-----+---------+------------+------+
| Id | Nom     | Age | Salaire | Profession | Dep  |
+----+---------+-----+---------+------------+------+
|  1 | Ismail  |  25 | 6000.00 | Assistant  |    2 |
|  2 | Mohamed |  30 | 8000.40 | Directeur  |    1 |
|  3 | Fatima  |  29 | 6000.00 | Directeur  |    3 |
|  4 | Dounia  |  30 | 7000.00 | Assistant  |    4 |
|  5 | Omar    |  30 | 9000.00 | Ingenieur  |    1 |
|  6 | Mostafa |  29 | 7500.00 | Ingenieur  |    3 |
+----+---------+-----+---------+------------+------+

Table - Projet

+------+------------+-----------+------------------+
| Id_p | Titre      | Cout      | Date_realisation |
+------+------------+-----------+------------------+
|    1 | SIG Meknes | 200000.00 | 2019-01-25       |
|    2 | SI Vente   | 130000.00 | 2019-03-12       |
|    3 | Blog RH    |  30000.00 | 2018-05-03       |
+------+------------+-----------+------------------+

Table - Participer

+-----+------+
| Emp | Proj |
+-----+------+
|   1 |    1 |
|   2 |    1 |
|   2 |    3 |
|   3 |    1 |
|   6 |    2 |
|   6 |    3 |
+-----+------+

Sous-requêtes avec l'instruction SELECT

Les sous-requêtes sont le plus souvent utilisées avec l'instruction SELECT. La syntaxe de base est la suivante :

   
Sous-requête avec SELECT SQL
SELECT colonne1 [, colonne2 ]
FROM   table1 [, table2 ]
WHERE  colonne OPERATOR
    (SELECT colonne1 [, colonne2 ]
     FROM table1 [, table2 ]
     [WHERE condition])

Il existe principalement deux types de sous-requêtes :

  • Sous-requêtes indépendantes (exécutées une seule fois)
  • Sous-requêtes corrélées (exécutées pour chaque ligne de la requête externe)

Sous-requêtes indépendantes

Principe

Dans les sous-requêtes indépendantes, l'exécution commence de la requête la plus interne vers la plus externe. L'exécution d'une requête interne est indépendante de la requête externe, mais le résultat est utilisé dans l'exécution de la requête externe.

Les opérateurs comme IN, NOT IN, ANY, ALL sont souvent utilisés.

  Exemple n°1

Trouver les Ids des employés qui participent aux projets "SI Vente" ou "Blog RH".

SELECT DISTINCT Emp FROM Participer 
WHERE Proj IN (SELECT Id_p FROM Projet WHERE Titre = "Blog RH" OR Titre = "SI Vente");
Résultat
+-----+
| Emp |
+-----+
|   2 |
|   6 |
+-----+

Explication :

  • La sous-requête interne trouve les Id_p des projets "Blog RH" et "SI Vente".
  • La requête externe utilise ces Id_p pour trouver les employés correspondants dans la table Participer.
  • Le résultat est 2 et 6 (Mohamed et Mostafa).

  Exemple n°2

Trouver les noms des départements dans lesquels un employé a participé à un projet.

SELECT Nom_dep FROM Departement 
WHERE Id_dep IN (SELECT DISTINCT E.Dep FROM Employes AS E INNER JOIN Participer AS P ON E.Id = P.Emp);
Résultat
+--------------+
| Nom_dep      |
+--------------+
| Informatique |
| RH           |
| Vente        |
+--------------+

Explication :

  • La sous-requête interne trouve les départements (Dep) des employés qui ont participé à au moins un projet.
  • La requête externe utilise ces Id_dep pour obtenir les noms des départements.
  • Résultat : Informatique, RH, Vente (le département Strategies n'a aucun participant).

  Exemple n°3

Trouver les employés qui ne participent à aucun projet.

SELECT Nom FROM Employes 
WHERE Id NOT IN (SELECT DISTINCT Emp FROM Participer);
Résultat
+--------+
| Nom    |
+--------+
| Dounia |
| Omar   |
+--------+

Sous-requêtes corrélées

Principe

Une sous-requête corrélée est une sous-requête dont le résultat dépend des valeurs de la ligne courante de la requête externe. Elle doit être exécutée pour chaque ligne extraite par la requête externe, ce qui peut avoir un impact sur les performances.

  Exemple n°4

Trouver les employés ayant le salaire maximum dans leur département respectif.

SELECT Nom FROM Employes AS e1 
WHERE e1.Salaire = (SELECT MAX(e2.Salaire) FROM Employes AS e2 WHERE e1.Dep = e2.Dep);
Résultat
+---------+
| Nom     |
+---------+
| Ismail  |
| Dounia  |
| Omar    |
| Mostafa |
+---------+

Explication :

  • Pour chaque employé e1, la sous-requête calcule le salaire maximum de son département (e1.Dep = e2.Dep).
  • La sous-requête est corrélée car elle dépend de la valeur de e1.Dep pour chaque ligne.
  • Résultat : les employés avec le salaire max dans chaque département.

Sous-requêtes vs jointures

Avantages des sous-requêtes
  • Simples à utiliser et à lire
  • Moins complexes que les jointures pour les débutants
  • Bien adaptées aux requêtes hiérarchiques
Inconvénients des sous-requêtes
  • Problèmes de performances potentiels
  • Une jointure peut être jusqu'à 500 fois plus rapide
  • Recommandation : utiliser une jointure quand c'est possible

Les sous-requêtes ne doivent être utilisées comme solution de secours que lorsque vous ne pouvez pas utiliser une opération JOIN pour atteindre les objectifs ci-dessus.

Sous-requêtes avec l'instruction INSERT

La sous-requête peut également être utilisée avec l'instruction INSERT. Les données renvoyées par la sous-requête sont utilisées pour être insérées dans une autre table.

Syntaxe

INSERT INTO table_dest [ (col1 [, col2 ]) ]
    SELECT [ *|col1 [, col2 ] ]
    FROM table_source [, table2 ]
    [ WHERE condition ]

  Exemple n°5

INSERT INTO Employes_SAUVEGARDE
    SELECT * FROM Employes;

Cette requête copie toutes les données de la table Employes vers la table Employes_SAUVEGARDE (qui doit avoir la même structure).

Sous-requêtes avec l'instruction UPDATE

La sous-requête peut être utilisée conjointement avec l'instruction UPDATE pour mettre à jour des colonnes en fonction d'une condition basée sur une autre table.

Syntaxe

UPDATE table
    SET colonne = nouvelle_valeur
    [ WHERE OPERATOR [ VALUE ]
        (SELECT colonne FROM table_source)
        [ WHERE condition ] ]

  Exemple n°6

UPDATE Employes  
    SET Salaire = Salaire * 0.25  
    WHERE Age IN (SELECT Age FROM Employes_SAUVEGARDE  
                  WHERE Age >= 30);

Cette requête augmente de 25% le salaire des employés dont l'âge est supérieur ou égal à 30 ans (en se basant sur la table de sauvegarde).

Résultat (table Employes après UPDATE)
+----+---------+-----+---------+------------+------+
| Id | Nom     | Age | Salaire | Profession | Dep  |
+----+---------+-----+---------+------------+------+
|  1 | Ismail  |  25 | 6000.00 | Assistant  |    2 |
|  2 | Mohamed |  30 | 2000.10 | Directeur  |    1 |
|  3 | Fatima  |  29 | 6000.00 | Directeur  |    3 |
|  4 | Dounia  |  30 | 1750.00 | Assistant  |    4 |
|  5 | Omar    |  30 | 2250.00 | Ingenieur  |    1 |
|  6 | Mostafa |  29 | 7500.00 | Ingenieur  |    3 |
+----+---------+-----+---------+------------+------+

Sous-requêtes avec l'instruction DELETE

La sous-requête peut être utilisée avec l'instruction DELETE pour supprimer des enregistrements basés sur une condition d'une autre table.

  Exemple n°7

DELETE FROM Employes  
    WHERE Age IN (SELECT Age FROM Employes_SAUVEGARDE  
                  WHERE Age <= 29);

Cette requête supprime les employés dont l'âge est inférieur ou égal à 29 ans (en se basant sur la table de sauvegarde).

Résultat (table Employes après DELETE)
+----+---------+-----+---------+------------+------+
| Id | Nom     | Age | Salaire | Profession | Dep  |
+----+---------+-----+---------+------------+------+
|  2 | Mohamed |  30 | 2000.10 | Directeur  |    1 |
|  4 | Dounia  |  30 | 1750.00 | Assistant  |    4 |
|  5 | Omar    |  30 | 2250.00 | Ingenieur  |    1 |
+----+---------+-----+---------+------------+------+

Récapitulatif

Type de sous-requêteDescriptionExécutionExemple d'opérateur
IndépendanteLa sous-requête ne dépend pas de la requête externeUne seule foisIN, NOT IN, ANY, ALL
CorréléeLa sous-requête dépend des valeurs de la requête externePour chaque ligne externe=, >, <, etc.
Points clés à retenir
  • Une sous-requête est une requête SELECT imbriquée dans une autre requête.
  • Les sous-requêtes doivent être entre parenthèses.
  • Elles renvoient généralement une seule colonne (sauf cas particuliers).
  • Deux types principaux : indépendantes et corrélées.
  • Les sous-requêtes corrélées peuvent être plus lentes (exécutées pour chaque ligne).
  • Elles peuvent être utilisées avec SELECT, INSERT, UPDATE, DELETE.
  • Préférer une jointure à une sous-requête pour de meilleures performances.
  • Opérateurs courants : IN, NOT IN, ANY, ALL, EXISTS, NOT EXISTS.
  • Une sous-requête peut renvoyer une valeur unique, une ligne ou un ensemble de lignes.

Discussion (0)

Soyez le premier à laisser un commentaire !

Laisser un commentaire

Votre commentaire sera visible après modération.