Widzę, że wiele osób korzysta z podkwerend lub funkcji specyficznych dla dostawców, aby to zrobić, ale często wykonuję tego rodzaju zapytania bez podkwerend w następujący sposób. Używa zwykłego, standardowego SQL, więc powinien działać w dowolnej marce 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;
Innymi słowy: pobierz wiersz z miejsca, w t1którym nie istnieje żaden inny wiersz z tym samymUserId i większej dacie.
(Umieszczam identyfikator „Data” w ogranicznikach, ponieważ jest to słowo zastrzeżone SQL).
W przypadku, gdy t1."Date" = t2."Date"pojawi się podwojenie. Zwykle tabele mają auto_inc(seq)klucz, np id. Aby uniknąć podwojenia, można zastosować:
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;
Ponownie skomentuj @Farhan:
Oto bardziej szczegółowe wyjaśnienie:
Zewnętrzna próbach przyłączenia do przyłączenia t1się t2. Domyślnie t1zwracane są wszystkie wyniki , a jeśli istnieje dopasowanie t2, jest ono również zwracane. Jeśli nie ma dopasowania t2dla danego wiersza t1, wówczas zapytanie nadal zwraca wiersz t1i używa NULLjako symbolu zastępczego dla wszystkicht2 kolumn. Tak właśnie działają sprzężenia zewnętrzne.
Sztuczka w tym zapytaniu polega na zaprojektowaniu warunków dopasowania łączenia, które t2muszą być takie same userid i większe date . Pomysł jest, jeśli wiersz istnieje t2, że ma większą date, wówczas wiersz t1to jest porównywana nie może być największym datena to userid. Ale jeśli nie ma dopasowania - tj. Jeśli nie istnieje żaden wiersz t2z wartością większą dateniż wiersz in t1- wiemy, że wiersz w t1był wierszem o największym datedla danego userid.
W tych przypadkach (gdy nie ma dopasowania), kolumny t2będą NULL- nawet kolumny określone w warunku łączenia. Dlatego używamy WHERE t2.UserId IS NULL, ponieważ szukamy przypadków, w których nie znaleziono żadnego wiersza z większym datedla podanego userid.