Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Pobierz wiersz, który ma maksymalną wartość dla kolumny

Widzę, że wiele osób używa do tego podzapytań lub funkcji okna, ale często wykonuję tego rodzaju zapytania bez podzapytań w następujący sposób. Używa zwykłego, standardowego SQL, więc powinien działać w każdej 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 t1 gdzie nie istnieje żaden inny wiersz z tym samym UserId i większą datę.

(Umieściłem identyfikator „Data” w ogranicznikach, ponieważ jest to słowo zastrzeżone SQL.)

W przypadku, gdy t1."Date" = t2."Date" , pojawia się podwojenie. Zwykle tabele mają auto_inc(seq) klucz, np. id .Aby uniknąć dublowania, można zastosować następujące:

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 komentarz od @Farhan:

Oto bardziej szczegółowe wyjaśnienie:

Złącze zewnętrzne próbuje dołączyć do t1 z t2 . Domyślnie wszystkie wyniki t1 są zwracane, a jeśli jest dopasowanie w t2 , to również jest zwracane. Jeśli nie ma dopasowania w t2 dla danego wiersza t1 , zapytanie nadal zwraca wiersz t1 i używa NULL jako symbol zastępczy dla wszystkich t2 kolumny. Tak właśnie działają generalnie sprzężenia zewnętrzne.

Sztuczka w tym zapytaniu polega na zaprojektowaniu warunku dopasowania sprzężenia w taki sposób, że t2 musi pasować do tego samego userid i większe date . Chodzi o to, że wiersz istnieje w t2 który ma większą date , a następnie wiersz w t1 jest porównywany z nie mogę bądź najlepszą date dla tego userid . Ale jeśli nie ma dopasowania -- tj. jeśli w t2 nie ma żadnego wiersza z większą date niż wiersz w t1 -- wiemy, że wiersz w t1 był wiersz z największą date dla podanego userid .

W takich przypadkach (gdy nie ma dopasowania) kolumny t2 będzie NULL -- nawet kolumny określone w warunku złączenia. Dlatego używamy WHERE t2.UserId IS NULL , ponieważ szukamy przypadków, w których nie znaleziono wiersza z większą date dla podanego userid .



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. jak uzyskać rowNum jak kolumnę w sqlite IPHONE

  2. Jak wstawić znacznik czasu w Oracle?

  3. Jak działa pobieranie danych z SQL Server do SqlDataReader?

  4. Funkcja NCHR() w Oracle

  5. Widok zmaterializowany a tabele:jakie są zalety?