IV.5.5. Sous-interrogations
Nous pouvons dire, qu'une caractéristique puissante de
SQL est la possibilité qu'un critère de recherche employé
dans une clause WHERE (expression à droite d'un opérateur de
comparaison) soit lui-même le résultat d'un SELECT ; c'est ce que
l'on appelle une sous-interrogation ou un
SELECT imbriqué. Cela permet de
réaliser des interrogations complexes qui nécessiteraient sinon
plusieurs interrogations avec stockage des résultats
intermédiaires.
Un SELECT peut retourner de zéro
à n lignes comme résultat. On a donc les cas suivants :
Une sous-interrogation ne retournant aucune ligne se termine
avec un code d'erreur, à moins d'utiliser l'opérateur EXISTS qui
retourne faux dans ce cas, vrai si la
sous-interrogation retourne au moins une ligne. Cet opérateur permet
d'empêcher l'exécution de l'interrogation principale si la sous
interrogation ne retourne aucun résultat, mais s'emploie surtout avec
les sous-interrogations synchronisées.
Cas pratique: Donner la liste des
noms et salaires des employés si un des salaires est inférieur
à 1000 :
SELECT nom, salaire FROM employes
WHERE EXISTS(SELECT * FROM employes WHERE salaire<1000);
Si le résultat d'une sous-interrogation ne
comportequ'une seule ligne, il peut être utilisé directement avec
les opérateurs de comparaison classiques.
Cas pratique : Donner le nom des
employés exerçant la même fonction que Victor :
SELECT nom FROM employes
WHERE fonction =(SELECT fonction FROM employes WHERE
nom='Victor');
Une sous-interrogation peut retourner plusieurs lignes
à condition que l'opérateur de comparaison admette à sa
droite un ensemble de valeurs. Les opérateurs permettant de comparer une
valeur à un ensemble de valeurs sont :
83
Tableau IV.1. Les opérateurs de comparaison d'une
valeur à un ensemble de valeurs Cas pratique:
Donner la liste des employés gagnant plus que tous ceux du
département 30 :
SELECT nom, salaire FROM employes
WHERE salaire > ALL(SELECT salaire FROM employes WHERE
_num_dep=30);
Sous-interrogation synchronisée avec l'interrogation
principale. Dans les exemples précédents, la sous-interrogation
était évaluée d'abord, puis son résultat
était utilisé pour exécuter l'interrogation principale.
SQL sait également traiter une sous-interrogation faisant
référence à une colonne de la table de l'interrogation
principale. Dans ce cas, le traitement est plus complexe car il faut
évaluer la sous interrogation pour chaque ligne de l'interrogation
principale.
Cas pratique: Donner la liste des
employés ne travaillant pas dans le même département que
leur supérieur :
SELECT nom FROM employes e
WHERE _num_dep<>(SELECT _num_dep FROM employes WHERE
e._superieur=num_emp)
AND _superieur IS NOT NULL;
Il a fallu ici renommer la table Employes de l'interrogation
principale pour pouvoir la référencer sans ambiguïté
dans la sous-interrogation. La dernière ligne est utile car le
président ne possède pas de supérieur (valeur NULL) et la
sous-interrogation ne retourne alors aucune valeur.
Cas pratique: Donner les
employés des départements qui n'ont pas embauché depuis le
début de l'année 1982 :
SELECT * FROM employes e
WHERE NOT EXISTS(SELECT * FROM employes WHERE
date_embauche>=to_date('01/01/1982','DD-MM-YYYY') AND
_num_dep=e._num_dep);
|