Ich sehe, dass viele Leute Unterabfragen oder herstellerspezifische Funktionen verwenden, um dies zu tun, aber ich mache diese Art von Abfrage oft ohne Unterabfragen auf folgende Weise. Es verwendet einfaches Standard-SQL, sodass es in jeder RDBMS-Marke funktionieren sollte.
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;
Mit anderen Worten: Rufen Sie die Zeile ab, von der t1
keine andere Zeile mit demselben UserId
und einem größeren Datum vorhanden ist.
(Ich habe den Bezeichner "Datum" in Trennzeichen gesetzt, da es sich um ein reserviertes SQL-Wort handelt.)
Falls t1."Date" = t2."Date"
, erscheint eine Verdoppelung. Normalerweise haben Tabellen auto_inc(seq)
Schlüssel, z id
. Um eine Verdoppelung zu vermeiden, kann Folgendes verwendet werden:
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;
Kommentar von @Farhan:
Hier ist eine detailliertere Erklärung:
Eine äußere Verknüpfung versucht, eine Verknüpfung t1
herzustellen t2
. Standardmäßig werden alle Ergebnisse von t1
zurückgegeben, und wenn eine Übereinstimmung vorliegt t2
, wird diese ebenfalls zurückgegeben. Wenn t2
für eine bestimmte Zeile von keine Übereinstimmung vorliegt t1
, gibt die Abfrage weiterhin die Zeile von zurück t1
und wird NULL
als Platzhalter für alle t2
Spalten von verwendet. So funktionieren äußere Verknüpfungen im Allgemeinen.
Der Trick bei dieser Abfrage besteht darin, die Übereinstimmungsbedingung des Joins so zu gestalten, dass sie t2
mit derselben übereinstimmt userid
und eine größere date
. Die Idee ist , wenn eine Zeile in besteht , t2
dass eine größere date
, dann die Zeile in t1
es verglichen kann nicht die größte sein , date
dafür userid
. Aber wenn es keine Übereinstimmung gibt - dh wenn keine Zeile t2
mit einer größeren date
als der Zeile in vorhanden ist t1
- wissen wir, dass die Zeile in t1
die Zeile mit der größten date
für die gegebene war userid
.
In diesen Fällen (wenn gibt es keine Übereinstimmung), der die Spalten t2
werden NULL
- auch die in der angegebenen Spalten Joinbedingung. Deshalb verwenden wir WHERE t2.UserId IS NULL
, weil wir nach Fällen suchen, in denen keine Zeile mit einer größeren date
für die angegebene gefunden wurde userid
.