Il s'agit du plus grand problème de n-par-groupe qui survient fréquemment sur Stack Overflow.
Voici ma réponse habituelle :
select
p.name player,
s.date first_score,
s.points points
from players p
join scores s
on s.player_id = p.id
left outer join scores s2
on s2.player_id = p.id
and s2.date < s.date
where
s2.player_id is null
;
En d'autres termes, étant donné le score s, essayez de trouver un score s2 pour le même joueur, mais avec une date antérieure. Si aucun score antérieur n'est trouvé, alors s est le plus ancien.
Concernant votre commentaire sur les égalités :vous devez avoir une politique pour laquelle utiliser en cas d'égalité. Une possibilité est que si vous utilisez des clés primaires à incrémentation automatique, celle qui a le moins de valeur est la plus ancienne. Voir le terme supplémentaire dans la jointure externe ci-dessous :
select
p.name player,
s.date first_score,
s.points points
from players p
join scores s
on s.player_id = p.id
left outer join scores s2
on s2.player_id = p.id
and (s2.date < s.date or s2.date = s.date and s2.id < s.id)
where
s2.player_id is null
;
Fondamentalement, vous devez ajouter des termes de départage jusqu'à ce que vous arriviez à une colonne qui est garantie d'être unique, au moins pour le joueur donné. La clé primaire de la table est souvent la meilleure solution, mais j'ai vu des cas où une autre colonne convenait.
Concernant les commentaires que j'ai partagés avec @OMG Ponies, rappelez-vous que ce type de requête bénéficie énormément du bon index.