Les requêtes imbriquées

Une requête imbriquée est une requête dont le résultat est utilisé par une autre requête.

On a déjà vu sur la page sur la création des tables qu’il était possible de créer une table à partir des résultats d’une requête:

tutorial=> create table famille_4 as select * from famille where date_de_naissance < '2000-01-01';
SELECT 2
tutorial=> select * from famille_4;
  nom   |  prenom   | date_de_naissance | id | residence
--------+-----------+-------------------+----+-----------
 Dupont | Michel    | 1956-12-31        |  2 | Paris
 Dupont | Madelaine | 1960-11-28        |  5 | Paris
(2 rows)

tutorial=>

Plus simplement, on peut simplement sélectionner des enregistrements en fonction du résultat d’une autre requête:

tutorial=> select nom, prenom from eleves where classe in (select id from classes where classe = 'Terminale');
     nom      | prenom
--------------+---------
 Sophie       | Favier
 Pierre       | Perret
 Jean Jacques | Goldman
(3 rows)

tutorial=>

Exactement de la même façon, on peut modifier ou supprimer des enregistrements en fonction du résultat d’une autre requête. Rajoutons une colonne dans notre table sur les élèves et donnons lui une valeur en fonction de la classe:

tutorial=> alter table eleves add column derniere_annee boolean;
ALTER TABLE
tutorial=> update eleves set derniere_annee = 't' where classe in (select id from classes where classe = 'Terminale');
UPDATE 3
tutorial=> select * from eleves;
 id |     nom      |  prenom  | classe | derniere_annee
----+--------------+----------+--------+----------------
  5 | Jacques      | Brel     |      2 |
  6 | Jacques      | Martin   |      3 |
  8 | Mel          | Gibson   |      2 |
  9 | François     | Hollande |      3 |
 11 | Donald       | Trump    |      2 |
 12 | Etienne      | Martin   |      3 |
  4 | Sophie       | Favier   |      1 | t
  7 | Pierre       | Perret   |      1 | t
 10 | Jean Jacques | Goldman  |      1 | t
(9 rows)

On peut d’ailleurs faire la même requête en fonction des résultats non retournés par une requête imbriquée:

tutorial=> update eleves set derniere_annee = 'f' where classe not in (select id from classes where classe = 'Terminale');
UPDATE 6
tutorial=> select * from eleves;
 id |     nom      |  prenom  | classe | derniere_annee
----+--------------+----------+--------+----------------
  4 | Sophie       | Favier   |      1 | t
  7 | Pierre       | Perret   |      1 | t
 10 | Jean Jacques | Goldman  |      1 | t
  5 | Jacques      | Brel     |      2 | f
  6 | Jacques      | Martin   |      3 | f
  8 | Mel          | Gibson   |      2 | f
  9 | François     | Hollande |      3 | f
 11 | Donald       | Trump    |      2 | f
 12 | Etienne      | Martin   |      3 | f
(9 rows)

Attention à l’utilisation du NOT IN qui n’est pas du tout optimisé, particulièrement sur les grosses tables.

index suite…