Aller au contenu

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 :

  1. Calculer la moyenne
  2. 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
    )
);
  1. Calcul moyenne globale
  2. Trouver les départements dont la moyenne est au-dessus
  3. Garder les employés de ces départements