title | theme | author | company | contributors | sources | |
---|---|---|---|---|---|---|
Sous requêtes |
solarized |
Alexandre Devos |
Octocorn |
|
-
Une sous-requête est une requête SQL imbriquée dans une autre requête SQL.
-
Elle peut être utilisée dans une clause
WHERE
,FROM
,SELECT
,INSERT
,UPDATE
ouDELETE
. -
Peut aussi servir à réaliser plusieurs opérations en une seule requête.
-
La sous-requête est exécutée en premier.
-
Elle ne retourne qu'une seule ligne
-
On utilise le résultat de la sous-requête dans une clause
WHERE
.
-- Requête principale
SELECT nom,
prenom
FROM eleves
WHERE classe_id =
-- Sous requête
(SELECT id
FROM classes
WHERE nom LIKE 'Troisième');
SELECT id
FROM classes
WHERE nom LIKE 'Troisième'
Dans notre cas, retourne
3
SELECT nom,
prenom
FROM eleves
WHERE classe_id = 3
Où 3 est le résultat de la sous requête
SELECT eleves.nom,
eleves.prenom
FROM eleves
LEFT JOIN classes
ON eleves.classe_id = classes.id
WHERE classes.nom LIKE 'Troisième';
-
Il faut favoriser les jointures
-
Une sous requête est plus lente qu'une jointure
Essayez avec
EXPLAIN
pour voir la différence !
- Si on a besoin de plusieurs résultats, on utilise le mot clef
IN
-- Requête principale
SELECT nom,
prenom
FROM eleves
WHERE classe_id IN (
(SELECT id
FROM classes
WHERE nom IN ('Troisième', 'Quatrième')))
- On peut aussi utiliser
ANY
SELECT nom,
prenom
FROM eleves
WHERE classe_id = ANY ((SELECT id
FROM classes
WHERE nom IN ('Troisième', 'Quatrième')))
Et pour faire une comparaison avec tous les résultats, on utilise ALL
SELECT nom,
prenom
FROM eleves
WHERE classe_id > ALL ((SELECT id
FROM classes
WHERE nom IN ('Troisième', 'Quatrième')))
On retour les élèves dont l'ID est supérieur à tous les ID des classes de troisième et quatrième
-
Fait référence à une colonne non reprise dans le
FROM
, mais présente ailleurs -
La sous requête seule ne pourra pas être exécutée
Ici, on cherche à vérifier si un élève est dans une classe de troisième.
SELECT classes.id, classes.nom FROM classes
WHERE EXISTS (
-- Ne pourra pas être exécutée seule
SELECT * FROM eleves
WHERE classes.nom = 'Troisième'
)
NB : cette requête est purement illustrative !
Les requêtes corrélées peuvent accéder uniquement aux niveaux supérieurs ! Jamais en dessous ni au même niveau !
On est un peu limité avec notre table eleves
. Vous aurez l'occasion de pratiquer avec la base beer
dans les
exercices.
-
La sous-requête est exécutée en premier.
-
Son résultat va servir de table pour la requête principale.
-
On réalise une requête sur la table virtuelle créée par la sous-requête.
Ca ne vous fait pas penser à quelque chose ?
-- Liste des colonnes à afficher
-- Doit faire référence à l'alias de la sous requête
SELECT eleves_avant_1950.nom,
eleves_avant_1950.prenom,
classes.nom
FROM (
-- Sous requête
SELECT eleves.nom,
eleves.prenom,
eleves.date_naissance,
eleves.classe_id
FROM eleves
WHERE YEAR(date_naissance) < 1950
-- Doit avoir un alias
) AS `eleves_avant_1950`
LEFT JOIN
classes ON classe_id = classes.id
WHERE classes.nom LIKE 'Sixième';
-- Création de la vue
CREATE VIEW `eleves_avant_1950` AS
SELECT eleves.nom,
eleves.prenom,
eleves.date_naissance,
eleves.classe_id
FROM eleves
WHERE YEAR(date_naissance) < 1950;
-- Utilisation de la vue
SELECT eleves_avant_1950.nom,
eleves_avant_1950.prenom,
classes.nom
FROM eleves_avant_1950
LEFT JOIN classes
ON classe_id = classes.id
WHERE classes.nom LIKE 'Sixième';
UNION
permet de mettre à la suite les résultats de deux requêtes
SELECT ...
UNION [ DISTINCT | ALL ]
SELECT ...
DISTINCT
: supprime les doublons (par défaut)ALL
: garde les doublons
NB : Les deux requêtes doivent avoir le même nombre de colonnes
Réaliser le TP 3 sur la base beer