Ich sehe, dass viele Leute Unterabfragen oder andere Fensterfunktionen verwenden, um dies zu tun, aber ich mache diese Art von Abfrage oft ohne Unterabfragen auf die folgende Weise. Es wird einfaches Standard-SQL verwendet, so dass es in jedem RDBMS 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: Holen Sie die Zeile aus t1
wo keine andere Zeile mit der gleichen UserId
und ein größeres Datum.
(Ich habe den Bezeichner "Datum" in Trennzeichen gesetzt, weil es sich um ein reserviertes SQL-Wort handelt).
Für den Fall, dass t1."Date" = t2."Date"
erscheint die Verdoppelung. Normalerweise hat Tabellen auto_inc(seq)
Schlüssel, z.B. id
. Um Verdoppelungen 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;
Zu dem Kommentar von @Farhan:
Hier ist eine ausführlichere Erklärung:
Eine äußere Verknüpfung versucht, die t1
con t2
. Standardmäßig werden alle Ergebnisse von t1
zurückgegeben werden, und si gibt es eine Übereinstimmung in t2
wird sie ebenfalls zurückgegeben. Wenn es keine Übereinstimmung in t2
für eine bestimmte Zeile von t1
dann gibt die Abfrage immer noch die Zeile von t1
und verwendet NULL
als Platzhalter für alle t2
Kolumnen. So funktionieren Outer Joins im Allgemeinen.
Der Trick bei dieser Abfrage besteht darin, die Abgleichsbedingung der Verknüpfung so zu gestalten, dass t2
muss mit dem dieselbe userid
und eine mehr date
. Die Idee ist, dass wenn eine Zeile in t2
die einen größeren date
dann die Zeile in t1
es wird verglichen mit kann nicht der Größte sein date
dafür userid
. Wenn es jedoch keine Übereinstimmung gibt - d. h. wenn keine Zeile in t2
mit einer größeren date
als die Zeile in t1
-- wir wissen, dass die Zeile in t1
war die Reihe mit den meisten date
für die angegebene userid
.
In diesen Fällen (wenn es keine Übereinstimmung gibt), werden die Spalten von t2
wird sein NULL
-- auch die in der Verknüpfungsbedingung angegebenen Spalten. Deshalb verwenden wir WHERE t2.UserId IS NULL
denn wir suchen nach den Fällen, in denen keine Zeile mit einem größeren Wert gefunden wurde. date
für die angegebene userid
.