Sous-requêtes (suite...)¶
Une sous‑requête est un SELECT placé à l’intérieur d’un autre SELECT.
Elle permet d’obtenir une information intermédiaire que la requête principale va utiliser.
Une sous‑requête peut renvoyer :
- une valeur unique (scalar subquery)
- une ligne
- une colonne
- un ensemble de lignes
Oracle exécute toujours la sous‑requête en premier, puis injecte son résultat dans la requête principale.
🧠 Pourquoi utiliser une sous-requête ?
Certaines questions nécessitent plusieurs étapes logiques :
❓ “Quels employés gagnent plus que la moyenne des salaires ?”
👉 On doit :
- Calculer la moyenne
- Comparer chaque employé à cette moyenne
➡️ Impossible en une seule étape simple
Sous-requêtes dans le FROM¶
🎯 Objectif : Calculer une valeur dérivée pour chaque ligne retournée
Exemple :
Afficher l'id des commandes et leur montant, ainsi que le montant moyen des commandes en colonne supplémentaire.
Requête :
SELECT
idCommande,
montantCommande,
moyenne_globale
FROM commandes,
(SELECT AVG(montantCommande) AS moyenne_globale
FROM commandes) ;
- Oracle calcule d’abord AVG(montant) dans la sous‑requête.
- Cette valeur unique est ajoutée à chaque ligne du SELECT principal (produit cartésien de deux tables).
💡 Quand c’est utile ?
✔ Ajouter des indicateurs globaux
✔ Comparer visuellement chaque ligne à une valeur de référence
Sous-requête dans une jointure¶
🎯 Objectif : filtrer une table avant de la joindre
Exemple :
Lister chaque département avec leur salaire moyen
SELECT nomDepartement, moyenne
FROM departement
INNER JOIN (
SELECT id_dept, AVG(salaire) AS moyenne
FROM employe
GROUP BY id_dept
) stats
ON departement.id_dept = stats.id_dept;
- La sous‑requête extrait de la table Employe la moyenne de salaire par département.
- Cette liste est ensuite jointe à la table Département.
💡 Quand c’est indispensable ?
✔ Quand on doit agréger avant de joindre
✔ Quand une jointure directe serait impossible
Sous‑requête dans un WHERE¶
🎯 Objectif : Filtrer selon une condition basée sur le résultat d'une autre requête
Exemple :
Afficher les employés ayant un salaire au-dessus de la moyenne.
Requête :
SELECT nom, salaire
FROM employe
WHERE salaire > (
SELECT AVG(salaire)
FROM employe
);
- La sous‑requête calcule la moyenne globale.
- Le WHERE compare le salaire à cette moyenne.
- Seuls les employes au‑dessus de la moyenne sont affichés.
💡 Cas d'utilisation le plus fréquent!
- utiliser > / < avec une valeur calculée
- utiliser IN avec une liste de résultats
- utiliser EXISTS pour vérifier une correspondance
Sous‑requête dans un HAVING¶
🎯 Objectif : filtrer les groupes en fonction d’une autre table
Exemple :
Afficher les clients dont le montant total de commandes dépasse la moyenne globale.
Requête :
SELECT id_client, SUM(montant) AS total_client
FROM commandes
GROUP BY id_client
HAVING SUM(montant) >
(SELECT AVG(montant) FROM commandes);
- La sous‑requête calcule la moyenne globale.
- Le HAVING compare chaque total client à cette moyenne.
- Seuls les clients au‑dessus de la moyenne sont affichés.
💡 Cas typiques
✔ Comparer des groupes entre eux
✔ Filtrer des agrégats avec une référence globale
Exemple à 2 niveaux d'imbrication¶
“Afficher les employés travaillant dans un département dont le salaire moyen est supérieur à la moyenne globale”
SELECT nom, id_dept
FROM employe
WHERE id_dept IN (
SELECT id_dept
FROM employe
GROUP BY id_dept
HAVING AVG(salaire) > (
SELECT AVG(salaire) FROM employe
)
);
- Calcul moyenne globale
- Trouver les départements dont la moyenne est au-dessus
- Garder les employés de ces départements