2012-01-17 116 views
18

Supongamos que puedo extraer un conjunto de datos.Oracle: Tomando el registro con la fecha máxima

decir

SELECT A, date 
FROM table 

Y quiero sólo el registro con la fecha max (para cada valor de A). Podría escribir

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) 

Pero mi consulta es muy largo ... ¿Hay una manera más compacta utilizando la función analítica a hacer lo mismo?

Respuesta

39

El enfoque de la función analítica haría mira algo así como

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 

Tenga en cuenta que dependiendo de cómo desea manejar los lazos (o si los vínculos son posibles en el modelo de datos), es posible que desee utilizar el ROW_NUMBER o la función analítica DENSE_RANK en lugar de RANK.

+0

¿Qué quiere decir con lazos? – Revious

+1

@ Gik25 - Un lazo se produciría si la hubiera, digamos, dos filas de 'TABLENAME' que tenían el mismo valor para' A' y el mismo valor para 'SOME_DATE_COLUMN'. Su consulta original devolvería ambas filas como las mías. Si, por el contrario, ha utilizado la función 'ROW_NUMBER', sólo una de las dos filas serían devueltos (aunque la elección de qué fila para volver sería arbitrario). –

15

Si date y col_date son las mismas columnas simplemente debe hacer:

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

Por qué no usar:

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 

lo contrario:

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

+1 El primer SQL es la respuesta más simple y mejor –

+1

@Matt: Sí, pero solo si el OP solo quiere estas 2 columnas y no toda la fila (como está implícito en la pregunta). –

+0

@ypercube estoy de acuerdo, y eso es lo que la pregunta parece –

6

También es posible usar:

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

Esto sería una buena opción si había un índice en '(a, col_date)', especialmente si hay un montón de fechas para cada valor distinto de A. – APC

+0

Esto funciona para mí. – GunWanderer

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

Esto no parece que coincida con la pregunta? –

1

Justin cueva respuesta es la mejor, pero si quieres antoher opción, intente esto:

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

muchas gracias –

1

A es la clave, max (fecha) es el valor, que podría simplificar la consulta de la siguiente manera:

SELECCIONAR distinta A, max (fecha) sobre (partición por A) FROM TABLENAME

Cuestiones relacionadas