Vidím, že mnoho lidí k tomu používá poddotazy nebo jiné funkce okna, ale často dělám tento druh dotazu bez poddotazů následujícím způsobem. Používá prostý standardní SQL, takže by měl fungovat v jakékoli značce 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;
Jinými slovy:načtěte řádek z t1 kde neexistuje žádný další řádek se stejným UserId a větší Datum.
(Identifikátor "Datum" jsem vložil do oddělovačů, protože je to slovo vyhrazené SQL.)
V případě, že t1."Date" = t2."Date" , objeví se zdvojení. Tabulky mají obvykle auto_inc(seq) klíč, např. id .Aby se zabránilo zdvojení, lze použít následující:
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;
Znovu komentář od @Farhan:
Zde je podrobnější vysvětlení:
Vnější spojení se pokusí připojit t1 s t2 . Ve výchozím nastavení jsou všechny výsledky t1 jsou vráceny a pokud existuje shoda v t2 , je také vrácen. Pokud v t2 není žádná shoda pro daný řádek t1 , pak dotaz stále vrací řádek t1 a používá NULL jako zástupný symbol pro všechny t2 sloupce . Takto fungují vnější spojení obecně.
Trik v tomto dotazu je navrhnout podmínku shody spojení tak, že t2 musí odpovídat stejnému userid a větší date . Myšlenka je, zda existuje řádek v t2 který má větší date , pak řádek v t1 je to porovnáno s nelze být největší date pro toto userid . Ale pokud neexistuje žádná shoda -- tj. pokud v t2 neexistuje žádný řádek s větším date než řádek v t1 -- víme, že řádek v t1 byl řádek s největším date pro dané userid .
V těchto případech (když neexistuje žádná shoda), sloupce t2 bude NULL -- dokonce i sloupce zadané v podmínce spojení. Proto používáme WHERE t2.UserId IS NULL , protože hledáme případy, kdy nebyl nalezen žádný řádek s větším date pro dané userid .