• Aucun résultat trouvé

3.4 Sous-requêtes

3.4.2 Sous-requêtes dans les conditions

Je vous ai donc dit que lorsque vous faites une requêteSELECT, le résultat est sous forme de table.

Ces tables de résultats peuvent avoir :

— plusieurs colonnes et plusieurs lignes ; — plusieurs colonnes mais une seule ligne ; — plusieurs lignes mais une seule colonne ;

— ou encore une seule ligne et une seule colonne (c’est-à-dire juste une valeur).

Les sous-requêtes renvoyant plusieurs lignes et plusieurs colonnes ne sont utilisées que dans les clausesFROM. Nous allons ici nous intéresser aux trois autres possibilités uniquement.

3.4.2.1 Comparaisons

Opérateur Signification = égal < inférieur <= inférieur ou égal > supérieur >= supérieur ou égal <> ou != différent

<=> égal (valable pourNULLaussi)

On peut utiliser des comparaisons de ce type avec des sous-requêtes qui donnent comme résul- tat soit une valeur (c’est-à-dire une seule ligne et une seule colonne), soit une ligne (plusieurs colonnes mais une seule ligne).

3.4.2.1.1 Sous-requête renvoyant une valeur

Le cas le plus simple est évidemment d’uti- liser une sous-requête qui renvoie une valeur.

SELECT id, sexe, nom, commentaires, espece_id, race_id

FROM Animal

WHERE race_id =

(SELECT id FROM Race WHERE nom = 'Berger Allemand'); -- la sous-requête renvoie simplement 1

Remarquez que cette requête peut également s’écrire avec une jointure plutôt qu’une sous- requête :

SELECT Animal.id, sexe, Animal.nom, commentaires, Animal.espece_id, race_id

FROM Animal

INNER JOIN Race ON Race.id = Animal.race_id

WHERE Race.nom = 'Berger Allemand';

Voici un exemple de requête avec sous-requête qu’il est impossible de faire avec une simple join- ture :

SELECT id, nom, espece_id

FROM Race

WHERE espece_id = (

SELECT MIN(id) -- Je rappelle que MIN() permet de récupérer la plus petite valeur de la colonne parmi les lignes sélectionnées

FROM Espece);

id nom espece_id

1 Berger allemand 1

2 Berger blanc suisse 1

3 Boxer 1

En ce qui concerne les autres opérateurs de comparaison, le principe est exactement le même : SELECT id, nom, espece_id

FROM Race

3.4 Sous-requêtes SELECT id

FROM Espece

WHERE nom_courant = 'Tortue d''Hermann');

id nom espece_id

1 Berger allemand 1

2 Berger blanc suisse 1

3 Boxer 1

4 Bleu russe 2

5 Maine coon 2

6 Singapura 2

7 Sphynx 2

Ici la sous-requête renvoie3, donc nous avons bien les races dont l’espèce a unidinférieur à 3 (donc 1 et 2 :p ).

3.4.2.1.2 Sous-requête renvoyant une ligne

[[attention]] | Seuls les opérateurs = et != (ou <>) sont utilisables avec une sous-requête de ligne, toutes les comparaisons de type “plus grand”

ou “plus petit” ne sont pas supportées.

Dans le cas d’une sous-requête dont le résultat est une ligne, la syntaxe est la suivante : SELECT *

FROM nom_table1

WHERE [ROW](colonne1, colonne2) = ( -- le ROW n'est pas obligatoire

SELECT colonneX, colonneY

FROM nom_table2

WHERE...); -- Condition qui ne retourne qu'UNE SEULE LIGNE

Cette requête va donc renvoyer toutes les lignes de la table1 dont la colonne1 = la colonneX de la ligne résultat de la sous-requête ET la colonne2 = la colonneY de la ligne résultat de la sous- requête.

Vous voulez un exemple peut-être ? Allons-y ! SELECT id, sexe, nom, espece_id, race_id

FROM Animal

WHERE (id, race_id) = (

SELECT id, espece_id

FROM Race

WHERE id = 7);

id sexe nom espece_id race_id

7 F Caroline 1 2

Décomposons calmement. Voyons d’abord ce que la sous-requête donne comme résultat. SELECT id, espece_id

FROM Race

WHERE id = 7;

id espece_id

7 2

Et comme condition, on aWHERE (id, race_id) = #le résultat de la sous-requête#.

Donc la requête renverra les lignes de la tableAnimalpour lesquellesidvaut 7 etrace_idvaut 2. [[attention]] | Attention, il est impératif que la sous-requête ne renvoie qu’une seule ligne. Dans le cas contraire, la requête échouera.

3.4.2.2 Conditions avec IN et NOT IN

3.4.2.2.1 IN

Vous connaissez déjà l’opérateurIN, qui compare une colonne avec une liste de

valeurs.

Exemple

SELECT Animal.id, Animal.nom, Animal.espece_id

FROM Animal

INNER JOIN Espece

ON Espece.id = Animal.espece_id

WHERE Espece.nom_courant IN ('Tortue d''Hermann', 'Perroquet amazone');

Cet opérateur peut également s’utiliser avec une sous-requête dont le résultat est une colonne ou une valeur. On peut donc réécrire la requête ci-dessus en utilisant une sous-requête plutôt qu’une jointure :

SELECT id, nom, espece_id

FROM Animal

WHERE espece_id IN (

SELECT id FROM Espece

WHERE nom_courant IN ('Tortue d''Hermann', 'Perroquet amazone') );

Le fonctionnement est plutôt facile à comprendre. La sous-requête donne les résultats suivants : SELECT id -- On ne sélectionne bien qu'UNE SEULE COLONNE.

FROM Espece

WHERE nom_courant IN ('Tortue d''Hermann', 'Perroquet amazone');

id 3 4

Ainsi, la requête principale sélectionnera les lignes qui ont unespece_idparmi ceux renvoyés par la sous-requête, donc 3 ou 4.

3.4 Sous-requêtes

3.4.2.2.2 NOT IN

Si l’on utiliseNOT IN, c’est bien sûr le contraire, on exclut les lignes qui correspondent au résultat de la sous-requête. La requête suivante nous renverra donc les animaux dont l’espece_idn’est pas 3 ou 4.

SELECT id, nom, espece_id

FROM Animal

WHERE espece_id NOT IN (

SELECT id FROM Espece

WHERE nom_courant IN ('Tortue d''Hermann', 'Perroquet amazone') );

3.4.2.3 Conditions avec ANY, SOME et ALL

Les conditions avecINetNOT INsont un peu limitées, puisqu’elles ne permettent que des com- paraisons de type “est égal” ou “est différent”. AvecANYetALL, on va pouvoir utiliser les autres

comparateurs (plus grand, plus petit, etc.).

[[attention]] | Bien entendu, comme pourIN, il faut des sous-requêtes dont le résultat est soit

une valeur, soit une colonne.

— ANY: veut dire “au moins une des valeurs”.

— SOME: est un synonyme deANY.

— ALL: signifie “toutes les valeurs”.

3.4.2.3.1 ANY (ou SOME)

La requête suivante signifie donc “Sélectionne les lignes de la tableAnimal, dont l’espece_idest inférieur à au moins une des valeurs sélectionnées dans la sous- requête”. C’est-à-dire inférieur à 3 ou à 4. Vous aurez donc dans les résultats toutes les lignes dont l’espece_idvaut 1, 2 ou 3 (puisque 3 est inférieur à 4).

SELECT *

FROM Animal

WHERE espece_id < ANY (

SELECT id FROM Espece

WHERE nom_courant IN ('Tortue d''Hermann', 'Perroquet amazone') );

3.4.2.3.2 ALL

Par contre, si vous utilisezALLplutôt queANY, cela signifiera “Sélectionne les

lignes de la tableAnimal, dont l’espece_idest inférieur à toutes les valeurs sélectionnées dans la sous-requête”. Donc inférieur à 3 et à 4. Vous n’aurez donc plus que les lignes dont l’espece_id vaut 1 ou 2.

SELECT *

FROM Animal

WHERE espece_id < ALL (

SELECT id FROM Espece

WHERE nom_courant IN ('Tortue d''Hermann', 'Perroquet amazone') );

3.4.2.3.3 Remarque : lien avec IN

Remarquez que= ANYest l’équivalent deIN, tandis que

<> ALLest l’équivalent deNOT IN. Attention cependant queANYetALL(et SOME) ne peuvent

s’utiliser qu’avec des sous-requêtes, et non avec des valeurs comme on peut le faire avecIN. On

ne peut donc pas faire ceci : SELECT id

FROM Espece

WHERE nom_courant = ANY ('Tortue d''Hermann', 'Perroquet amazone');

####1064 - You have an error in your SQL syntax;