Jeg ser mange mennesker bruger underforespørgsler eller vinduesfunktioner til at gøre dette, men jeg laver ofte denne form for forespørgsel uden underforespørgsler på følgende måde. Det bruger almindelig standard SQL, så det burde fungere i ethvert mærke af 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 andre ord:hent rækken fra t1
hvor der ikke findes en anden række med samme UserId
og en større dato.
(Jeg sætter identifikatoren "Dato" i skilletegn, fordi det er et reserveret SQL-ord.)
I tilfælde af, at t1."Date" = t2."Date"
, vises fordobling. Normalt har tabeller auto_inc(seq)
nøgle, f.eks. id
.For at undgå fordobling kan bruges følgende:
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 fra @Farhan:
Her er en mere detaljeret forklaring:
En ydre joinforbindelse forsøger at tilslutte sig t1
med t2
. Som standard er alle resultater af t1
returneres, og hvis der er et match i t2
, er det også returneret. Hvis der ikke er noget match i t2
for en given række af t1
, så returnerer forespørgslen stadig rækken af t1
, og bruger NULL
som en pladsholder for alle t2
's kolonner. Sådan fungerer udvendige samlinger generelt.
Tricket i denne forespørgsel er at designe sammenkædningens matchende tilstand, således at t2
skal matche samme userid
, og en større date
. Ideen er, om der findes en række i t2
der har en større date
, derefter rækken i t1
det sammenlignes med kan ikke være den største date
for det userid
. Men hvis der ikke er nogen match -- dvs. hvis der ikke findes en række i t2
med en større date
end rækken i t1
-- vi ved, at rækken i t1
var rækken med den største date
for det givne userid
.
I disse tilfælde (når der ikke er noget match), kolonnerne i t2
vil være NULL
-- selv de kolonner, der er angivet i forbindelsesbetingelsen. Så det er derfor, vi bruger WHERE t2.UserId IS NULL
, fordi vi søger efter de tilfælde, hvor der ikke blev fundet en række med en større date
for det givne userid
.