La soluzione corretta è:
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
Come funziona:
Corrisponde a ogni riga da o
con tutte le righe di b
avente lo stesso valore nella colonna Group
e un valore maggiore nella colonna Age
. Qualsiasi riga da o
non avendo il valore massimo del suo gruppo nella colonna Age
corrisponderà a una o più righe da b
.
Il LEFT JOIN
fa corrispondere la persona più anziana del gruppo (comprese le persone che sono sole nel loro gruppo) con una riga piena di NULL
s da b
("nessuna età maggiore nel gruppo").
Utilizzo di INNER JOIN
rende queste righe non corrispondenti e vengono ignorate.
Il WHERE
la clausola mantiene solo le righe con NULL
s nei campi estratti da b
. Sono le persone più anziane di ogni gruppo.
Ulteriori letture
Questa soluzione e molte altre sono spiegate nel libro SQL Antipatterns:Evitare le insidie della programmazione di database