2012-01-17 15 views
18

Załóżmy, że wyodrębniam niektóre dane.Oracle: Pobranie rekordu z datą maksymalną

tj

SELECT A, date 
FROM table 

I chcę tylko zapis z datą max (dla każdej wartości A). Mógłbym napisać

SELECT A, col_date 
    FROM TABLENAME t_ext 
WHERE col_date = (SELECT MAX (col_date) 
        FROM TABLENAME t_in 
        WHERE t_in.A = t_ext.A) 

Ale moje zapytanie jest naprawdę długa ... jest tam najbardziej kompaktowy sposób za pomocą analitycznych funkcji, aby zrobić to samo?

Odpowiedz

39

Podejście analityczne funkcja Czy wyglądać jak

SELECT a, some_date_column 
    FROM (SELECT a, 
       some_date_column, 
       rank() over (partition by a order by some_date_column desc) rnk 
      FROM tablename) 
WHERE rnk = 1 

Należy pamiętać, że w zależności od tego, jak chcesz obsługiwać więzi (czy krawaty są możliwe w modelu danych), użytkownik może chcieć użyć albo ROW_NUMBER lub funkcja analityczna DENSE_RANK zamiast RANK.

+0

Co masz na myśli mówiąc o krawatach? – Revious

+1

@ Gik25 - Remis wystąpiłby, gdyby były, powiedzmy, dwa wiersze w 'TABLENAME', które miały taką samą wartość dla' A' i taką samą wartość dla 'SOME_DATE_COLUMN'. Twoje pierwotne zapytanie zwróci oba te wiersze, tak jak ja. Jeśli, z drugiej strony, używałbyś funkcji 'ROW_NUMBER', zwracany byłby tylko jeden z dwóch wierszy (chociaż wybór, który wiersz ma zostać zwrócony, byłby dowolny). –

15

Jeśli date i col_date są te same kolumny należy po prostu zrobić:

SELECT A, MAX(date) FROM t GROUP BY A 

Dlaczego nie używać:

WITH x AS (SELECT A, MAX(col_date) m FROM TABLENAME) 
SELECT A, date FROM TABLENAME t JOIN x ON x.A = t.A AND x.m = t.col_date 

Inaczej:

SELECT A, FIRST_VALUE(date) KEEP(dense_rank FIRST ORDER BY col_date DESC) 
    FROM TABLENAME 
GROUP BY A 
+1

+1 Pierwszy SQL jest najprostszą i najlepszą odpowiedzią –

+1

@Matt: Tak, ale tylko wtedy, gdy OP chce tylko tych 2 kolumn, a nie całego wiersza (jak to jest sugerowane w pytaniu). –

+0

@ypercube Zgadzam się i tak wygląda pytanie –

6

Można również użyć:

SELECT t.* 
    FROM 
     TABLENAME t 
    JOIN 
     (SELECT A, MAX(col_date) AS col_date 
      FROM TABLENAME 
      GROUP BY A 
     ) m 
     ON m.A = t.A 
     AND m.col_date = t.col_date 
+1

Byłby to dobry wybór, gdyby istniał indeks na '(a, col_date)', szczególnie jeśli istnieje wiele dat dla każdej odrębnej wartości A. – APC

+0

To działa dla mnie. – GunWanderer

-3
SELECT mu_file, mudate 
    FROM flightdata t_ext 
WHERE mudate = (SELECT MAX (mudate) 
        FROM flightdata where mudate < sysdate) 
+0

To nie wygląda na to, że pasuje do pytania? –

1

Justin Cave odpowiedź jest najlepszy, ale jeśli chcesz antoher opcję, spróbuj tego:

select A,col_date 
from (select A,col_date 
    from tablename 
     order by col_date desc) 
     where rownum<2 
+1

dziękuję bardzo –

1

A jest kluczem, max (data) to wartość, możemy uprościć zapytanie jak poniżej:

WYBIERZ wyraźny A, maks. (data) powyżej (partycja A) Z TABLENAME

Powiązane problemy