Dans certaines requêtes, la condition WHERE est déterminée par le résultat d'une autre requête. La condition sera donc déterminée par une requête imbriquée, aussi appelé sous-requête.
Il s'agit de faire un SELECT dans un SELECT.
Ex : pour trouver le nom du ou des derniers mécaniciens embauchés :
SELECT prenom, nomfamille
FROM mecaniciens
WHERE embauche =
(
SELECT MAX(embauche)
FROM mecaniciens
);
Voici l'explication : lorsque le SGBD exécute la requête, il doit trouver la date maximale d’embauche puis il doit trouver les mécaniciens qui ont été embauchés à cette date. Il fait donc au total deux requêtes, d’où le besoin d’effectuer une sous-requête.
Notez que lorsque la première requête spécifie qu'un champ doit être comparé à la sous-requête (=, <, >, ...), la sous-requête devra ne retourner qu'un seul enregistrement.
Lors de l'exécution de la requête, la sous-requête sera toujours exécutée en premier.
MySQL supporte les requêtes imbriquées depuis la version 4.1
Les quelques contre-exemples suivants vous aideront à déceler le problème pour les erreurs les plus fréquemment commises.
Si vous entrez la requête suivante (notez l'absence de parenthèses de la sous-requête) :
phpMyAdmin vous donnera le message : erreur #1064 - Erreur de syntaxe près de 'SELECT MAX(embauche) FROM mecaniciens' à la ligne 4.
Il est donc impossible d'effectuer une sous-requête sans l'entourer de parenthèses.
Les novices peuvent être tentés de monter la requête suivante :
phpMyAdmin vous donnera le message : erreur #1111 - Utilisation invalide de la clause GROUP.
Voici une autre tentative pour obtenir le résultat sans effectuer de sous-requête :
Cette requête semble fonctionner. Cependant, on n’obtient pas le bon nom. Pourquoi? Le SGBD tente de lister les noms donc commence par sortir le premier nom de la liste. Comme une des informations demandées utilise une fonction d’agrégation, il sort le résultat de la fonction et, comme une fonction d’agrégation ne retourne qu’un enregistrement, il arrête le travail. On voit donc qu’il doit vraiment exécuter 2 requête pour réussir son travail.
Rappelez-vous de toujours vérifier les résultats d'une requête en consultant les données brutes de la BD avant de conclure que la requête est correcte.
Tentons un dernier essai :
SELECT prenom, nomfamille
FROM mecaniciens
ORDER BY embauche DESC
LIMIT 1;
Ici encore, la requête semble fonctionner. Cependant, cette requête ne retourne qu'un enregistrement alors qu'il y a deux personnes embauchées à la date la plus récente. Si on ne vérifie pas les informations dans la BD, on risque de ne jamais se rendre compte de l'erreur...
Il a été précisé que lorsque la sous-requête est utilisée dans une égalité, elle ne doit retourner qu'un seul enregistrement. Voici ce qui arrivera si ce n'est pas le cas.
phpMyAdmin retournera l'erreur suivante : #1242 - Subquery returns more than 1 row.
Si cela vous arrive, vous comprendrez que la sous-requête retourne plus d'un enregistrement donc elle doit être corrigée, possiblement à l'aide d'une fonction d'agrégation.
▼Publicité