Je vois que beaucoup de gens utilisent des sous-requêtes ou bien des fonctionnalités spécifiques au fournisseur pour ce faire, mais je fais souvent ce type de requête sans sous-requêtes de la manière suivante. Il utilise du SQL standard simple et devrait donc fonctionner dans n'importe quelle marque de SGBDR.
SELECT t1.*
FROM mytable t1
LEFT OUTER JOIN mytable t2
ON (t1.UserId = t2.UserId AND t1."Date" < t2."Date")
WHERE t2.UserId IS NULL;
En d'autres termes: récupérer la ligne d' t1où aucune autre ligne n'existe avec la même date UserIdet une date supérieure.
(J'ai mis l'identifiant "Date" dans les délimiteurs car c'est un mot réservé SQL.)
Dans le cas où t1."Date" = t2."Date", un doublement apparaît. Les tables ont généralement une auto_inc(seq)clé, par exemple id. Pour éviter le doublement peut être utilisé comme suit:
SELECT t1.*
FROM mytable t1
LEFT OUTER JOIN mytable t2
ON t1.UserId = t2.UserId AND ((t1."Date" < t2."Date")
OR (t1."Date" = t2."Date" AND t1.id < t2.id))
WHERE t2.UserId IS NULL;
Re commentaire de @Farhan:
Voici une explication plus détaillée:
Une jointure externe tente de se joindre t1à t2. Par défaut, tous les résultats de t1sont renvoyés et s'il y a une correspondance t2, elle est également renvoyée. S'il n'y a pas de correspondance t2pour une ligne donnée de t1, la requête renvoie toujours la ligne de t1et utilise NULLcomme espace réservé pour toust2 les colonnes de. C'est ainsi que les jointures externes fonctionnent en général.
L'astuce dans cette requête consiste à concevoir la condition de correspondance de la jointure telle qu'elle t2doit correspondre à la même userid et à une plus grande date . L'idée étant que s'il existe une ligne t2qui a un plus grand date, alors la ligne dans laquelle t1elle est comparée ne peut pas être la meilleure datepour cela userid. Mais s'il n'y a pas de correspondance - c'est-à-dire s'il n'y a pas de ligne t2avec une plus grande dateque la ligne en t1- nous savons que la ligne en t1était la ligne avec le plus grand datepour le donné userid.
Dans ces cas (lorsqu'il n'y a pas de correspondance), les colonnes de t2seront NULL- même les colonnes spécifiées dans la condition de jointure. C'est pourquoi nous utilisons WHERE t2.UserId IS NULL, car nous recherchons les cas où aucune ligne n'a été trouvée avec un plus grand datepour le donné userid.