Les sous-requêtes en SQL
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.
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 :
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
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");+-----+ | 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);+--------------+ | 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);+--------+ | Nom | +--------+ | Dounia | | Omar | +--------+
Sous-requêtes corrélées
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);+---------+ | 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
- Simples à utiliser et à lire
- Moins complexes que les jointures pour les débutants
- Bien adaptées aux requêtes hiérarchiques
- 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).
+----+---------+-----+---------+------------+------+ | 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).
+----+---------+-----+---------+------------+------+ | 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ête | Description | Exécution | Exemple d'opérateur |
|---|---|---|---|
| Indépendante | La sous-requête ne dépend pas de la requête externe | Une seule fois | IN, NOT IN, ANY, ALL |
| Corrélée | La sous-requête dépend des valeurs de la requête externe | Pour chaque ligne externe | =, >, <, etc. |
- 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.