informatique (tronc commun des prépas scientifiques) · Chapitre 16 · Exercice de TD
Le superlatif par groupe — un vrai piège
SQL : jointures, agrégation et requêtes imbriquées · niveau 2
Énoncé
On souhaite obtenir, pour chaque auteur, le titre de son livre le plus récent. (a) Expliquer pourquoi la requête SELECT nom, titre, MAX(annee) ... GROUP BY nom est incorrecte vis-à-vis du standard SQL et décrire le comportement potentiellement erroné de certains moteurs. (b) Construire une solution correcte en utilisant une sous-requête corrélée.
Corrigé
(a) Cette formulation viole la règle d'or SQL99 car l'attribut titre apparaît dans la projection SELECT sans être mentionné dans le GROUP BY, ni faire l'objet d'une agrégation. Dans le cas de Jules Verne, qui possède 3 livres, le moteur ne peut pas déterminer de manière univoque quel titre afficher. Si certains SGBD permissifs acceptent cette requête, ils renvoient un titre choisi arbitrairement, qui ne correspond pas nécessairement à l'année maximale trouvée. (b) La solution standard consiste à filtrer les livres pour ne garder que ceux dont l'année de publication est égale à la date maximale des livres du même auteur. On utilise pour cela une sous-requête corrélée dans la clause WHERE :
SELECT nom, titre, annee
FROM livre AS l JOIN auteur ON l.id_auteur = auteur.id_auteur
WHERE annee = (SELECT MAX(annee) FROM livre AS l2
WHERE l2.id_auteur = l.id_auteur);
Résultat :
Verne | Michel Strogoff | 1876
Austen | Orgueil et préjugés | 1813
Tolstoï | Anna Karénine | 1877
Colette | Le Blé en herbe | 1923
Ici, la sous-requête fait référence à l'alias l de la requête externe via la condition l2.id_auteur = l.id_auteur. Elle s'exécute pour chaque ligne évaluée par la requête globale (principe de corrélation). Cette approche gère correctement d'éventuels ex æquo.
Exercices semblables
- Le palmarès des livres — et ses absents corrigé
WHEREouHAVING? Les quatre combinaisons corrigé- Autojointures corrigé
- Le palmarès des villes corrigé
- La moyenne des moyennes n'est pas la moyenne corrigé