La bonne solution est :
SELECT o.*
FROM `Persons` o # 'o' from 'oldest person in group'
LEFT JOIN `Persons` b # 'b' from 'bigger age'
ON o.Group = b.Group AND o.Age < b.Age
WHERE b.Age is NULL # bigger age not found
Comment ça marche :
Il correspond à chaque ligne de o
avec toutes les lignes de b
ayant la même valeur dans la colonne Group
et une plus grande valeur dans la colonne Age
. N'importe quelle ligne de o
ne pas avoir la valeur maximale de son groupe dans la colonne Age
correspondra à une ou plusieurs lignes de b
.
Le LEFT JOIN
fait correspondre la personne la plus âgée du groupe (y compris les personnes qui sont seules dans leur groupe) avec une ligne pleine de NULL
s de b
('pas d'âge le plus élevé dans le groupe').
Utiliser INNER JOIN
rend ces lignes non concordantes et elles sont ignorées.
Le WHERE
la clause ne garde que les lignes ayant NULL
s dans les champs extraits de b
. Ce sont les personnes les plus âgées de chaque groupe.
Autres lectures
Cette solution et bien d'autres sont expliquées dans le livre SQL Antipatterns:Avoiding the Pitfalls of Database Programming