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 t1keine andere Zeile mit demselben UserIdund 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 t1herzustellen t2. Standardmäßig werden alle Ergebnisse von t1zurückgegeben, und wenn eine Übereinstimmung vorliegt t2, wird diese ebenfalls zurückgegeben. Wenn t2für eine bestimmte Zeile von keine Übereinstimmung vorliegt t1, gibt die Abfrage weiterhin die Zeile von zurück t1und wird NULLals Platzhalter für alle t2Spalten 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 t2mit derselben übereinstimmt useridund eine größere date . Die Idee ist , wenn eine Zeile in besteht , t2dass eine größere date, dann die Zeile in t1es verglichen kann nicht die größte sein , datedafür userid. Aber wenn es keine Übereinstimmung gibt - dh wenn keine Zeile t2mit einer größeren dateals der Zeile in vorhanden ist t1- wissen wir, dass die Zeile in t1die Zeile mit der größten datefür die gegebene war userid.
In diesen Fällen (wenn gibt es keine Übereinstimmung), der die Spalten t2werden 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 datefür die angegebene gefunden wurde userid.