Ik zie dat veel mensen subquery's of andere vensterfuncties gebruiken om dit te doen, maar ik doe dit soort query's vaak zonder subquery's op de volgende manier. Het gebruikt gewone, standaard SQL, dus het zou in elk merk RDBMS moeten werken.
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;
Met andere woorden:haal de rij op uit t1
waar geen andere rij bestaat met dezelfde UserId
en een grotere datum.
(Ik heb de identifier "Datum" tussen scheidingstekens gezet omdat het een gereserveerd SQL-woord is.)
In het geval dat t1."Date" = t2."Date"
, verdubbeling verschijnt. Meestal hebben tabellen auto_inc(seq)
sleutel, bijv. id
.Om verdubbeling te voorkomen kan het volgende worden gebruikt:
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 reactie van @Farhan:
Hier is een meer gedetailleerde uitleg:
Een outer join probeert lid te worden van t1
met t2
. Standaard worden alle resultaten van t1
worden geretourneerd, en indien er is een overeenkomst in t2
, het wordt ook teruggestuurd. Als er geen overeenkomst is in t2
voor een gegeven rij van t1
, dan retourneert de query nog steeds de rij van t1
, en gebruikt NULL
als tijdelijke aanduiding voor heel t2
's kolommen. Zo werken outer joins in het algemeen.
De truc in deze query is om de overeenkomende voorwaarde van de join zo te ontwerpen dat t2
moet overeenkomen met hetzelfde userid
, en een grotere date
. Het idee is of er een rij bestaat in t2
die een grotere date
heeft , dan de rij in t1
het wordt vergeleken met kan niet wees de beste date
voor dat userid
. Maar als er geen overeenkomst is -- d.w.z. als er geen rij bestaat in t2
met een grotere date
dan de rij in t1
-- we weten dat de rij in t1
was de rij met de beste date
voor de opgegeven userid
.
In die gevallen (wanneer er geen overeenkomst is), worden de kolommen van t2
wordt NULL
-- zelfs de kolommen die zijn opgegeven in de join-voorwaarde. Daarom gebruiken we WHERE t2.UserId IS NULL
, omdat we zoeken naar de gevallen waarin geen rij is gevonden met een grotere date
voor de opgegeven userid
.