Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Rufen Sie die Zeile ab, die den Max-Wert für eine Spalte enthält

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 verwendet einfaches, standardmäßiges 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:Holen Sie die Zeile aus t1 wobei keine andere Zeile mit derselben UserId vorhanden ist und ein größeres Datum.

(Ich habe den Bezeichner "Datum" in Trennzeichen gesetzt, weil es ein von SQL reserviertes Wort ist.)

Falls t1."Date" = t2."Date" , Verdopplung erscheint. 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;

Re-Kommentar von @Farhan:

Hier ist eine ausführlichere Erklärung:

Ein äußerer Join versucht, t1 zu verbinden mit t2 . Standardmäßig alle Ergebnisse von t1 zurückgegeben werden, und if es gibt eine Übereinstimmung in t2 , es wird auch zurückgegeben. Wenn es keine Übereinstimmung in t2 gibt für eine bestimmte Zeile von t1 , dann gibt die Abfrage immer noch die Zeile von t1 zurück , und verwendet NULL als Platzhalter für alles von t2 's Spalten. So funktionieren Outer Joins im Allgemeinen.

Der Trick bei dieser Abfrage besteht darin, die Übereinstimmungsbedingung des Joins so zu gestalten, dass t2 muss gleich übereinstimmen userid , und ein größer date . Die Idee ist, ob eine Zeile in t2 existiert das ein größeres date hat , dann die Zeile in t1 es wird mit kann nicht verglichen das größte date sein für diese userid . Aber wenn es keine Übereinstimmung gibt – d. h. wenn keine Zeile in t2 existiert mit einem größeren date als die Zeile in t1 -- wir wissen, dass die Zeile in t1 war die Zeile mit dem größten date für die angegebene userid .

In diesen Fällen (wenn es keine Übereinstimmung gibt), die Spalten von t2 wird NULL sein -- sogar die in der Join-Bedingung angegebenen Spalten. Deshalb verwenden wir WHERE t2.UserId IS NULL , weil wir nach den Fällen suchen, in denen keine Zeile mit einem größeren date gefunden wurde für die angegebene userid .