Jag ser att många använder subqueries eller fönsterfunktioner för att göra detta, men jag gör ofta den här typen av fråga utan subqueries på följande sätt. Den använder vanlig, standard SQL så den borde fungera i alla märken av RDBMS.
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;
Med andra ord:hämta raden från t1
där ingen annan rad finns med samma UserId
och ett större datum.
(Jag sätter identifieraren "Datum" i avgränsare eftersom det är ett reserverat SQL-ord.)
I fallet om t1."Date" = t2."Date"
, visas en fördubbling. Vanligtvis har tabeller auto_inc(seq)
nyckel, t.ex. id
.För att undvika fördubbling kan användas följande:
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;
Om kommentar från @Farhan:
Här är en mer detaljerad förklaring:
En yttre koppling försöker ansluta till t1
med t2
. Som standard är alla resultat av t1
returneras och om det finns en matchning i t2
, den återlämnas också. Om det inte finns någon matchning i t2
för en given rad med t1
, då returnerar frågan fortfarande raden t1
, och använder NULL
som platshållare för alla t2
s kolumner. Det är bara så ytterskarvar fungerar i allmänhet.
Tricket i den här frågan är att utforma kopplingens matchningsvillkor så att t2
måste matcha samma userid
och en större date
. Tanken är om det finns en rad i t2
som har ett större date
, sedan raden i t1
det jämförs med kan inte vara det största date
för det userid
. Men om det inte finns någon matchning -- dvs om det inte finns någon rad i t2
med ett större date
än raden i t1
-- vi vet att raden i t1
var raden med störst date
för det givna userid
.
I de fallen (när det inte finns någon matchning), kolumnerna i t2
kommer att vara NULL
-- även de kolumner som anges i kopplingsvillkoret. Så det är därför vi använder WHERE t2.UserId IS NULL
, eftersom vi söker efter fall där ingen rad hittades med ett större date
för det givna userid
.