2012-01-17 9 views
18

Supponiamo di estrarre un set di dati.Oracle: registrare il record con la data massima

cioè

SELECT A, date 
FROM table 

E voglio solo il record con la data massima (per ogni valore di A). Potrei scrivere

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) 

Ma la mia domanda è davvero lunga ... c'è un modo più compatto con funzione analitica di fare lo stesso?

risposta

39

L'approccio funzione analitica avrebbe assomiglia a

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 

Si noti che a seconda di come si desidera gestire i legami (o se i legami sono possibili nel vostro modello di dati), si consiglia di utilizzare il ROW_NUMBER o la funzione analitica DENSE_RANK piuttosto che RANK.

+0

Cosa intendi con le cravatte? – Revious

+1

@ Gik25 - Si verificherà un pareggio se, ad esempio, esistessero due righe in "TABLENAME' che avevano lo stesso valore per" A "e lo stesso valore per" SOME_DATE_COLUMN ". La tua query originale restituirebbe entrambe quelle righe come sarebbe mia. Se, d'altra parte, hai usato la funzione 'ROW_NUMBER', solo una delle due righe verrebbe restituita (anche se la scelta della riga da restituire sarebbe arbitraria). –

15

Se date e col_date sono le stesse colonne si dovrebbe semplicemente fare:

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

perché non utilizzare:

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 

Altrimenti:

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

+1 Il primo SQL è la più semplice e la migliore risposta –

+1

@Matt: Sì, ma solo se l'OP desidera solo queste 2 colonne e non l'intera riga (come è implicito nella domanda). –

+0

@ypercube Sono d'accordo, e questo è come appare la domanda –

6

Si potrebbe anche usare:

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

Questa sarebbe una buona scelta se ci fosse un indice su '(a, col_date)', specialmente se ci sono molte date per ciascun valore distinto di A. – APC

+0

Questo funziona per me. – GunWanderer

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

Non sembra che corrisponda alla domanda? –

1

Justin Cave risposta è il migliore, ma se si vuole antoher opzione, provate questo:

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

grazie mille –

1

A è la chiave, max (data) è il valore, potremmo semplificare la query come di seguito:

SELECT distinto A, max (data) sopra (partizione di A) DA TABLENAME