2012-01-09 8 views
6

tengo esta tabla:Oracle SQL: conseguir sólo una fila máximo mediante múltiples criterios de

Department NAME EMAIL   ID  DATE1   DATE2 
1   John [email protected] 74  05/04/2007 05/04/2007 
1   Sam [email protected] 23  05/04/2007 05/04/2007 
1   Tom [email protected] 46  05/04/2007 03/04/2007 
1   Bob [email protected] 23  01/01/2006 
2   Tom [email protected] 62  02/02/2000 05/05/1997 

Quiero conseguir la fila (sólo uno por departamento) con un máximo de DATE1, pero no es único! Entonces, si hay múltiples resultados, quiero obtener el máximo de DATE2, y si hay varios, se devuelve el que tiene la ID más grande.

Así que hay resultado de la consulta sería:

1   John [email protected] 74  05/04/2007 05/04/2007 
2   Tom [email protected] 62  02/02/2000 05/05/1997 

Muchas gracias.

Respuesta

18

Es necesario utilizar la función ROW_NUMBER:

SELECT Department, NAME, EMAIL, ID, DATE1, DATE2 
FROM (
SELECT ROW_NUMBER() OVER (PARTITION BY Department ORDER BY DATE1 DESC, DATE2 DESC, ID DESC) AS RowNumber, 
     Department, NAME, EMAIL, ID, DATE1, DATE2 
FROM MyTable) t 
WHERE RowNumber = 1 
+0

que suenan muy bien! funciona para una partición por varias columnas? porque mi tabla es mucho más complicada – jllopezpino

+0

@ user337746 - Sí, 'partition by' funciona exactamente como lo hace una instrucción' group by'. – Eric

+0

sí, la partición por es similar a la cláusula group by pero para la función Row_Number –

5

Uso de la cláusula de over:

select 
    * 
from 
    (
    select 
     Department, 
     Name, 
     Email, 
     ID, 
     DATE1, 
     DATE2, 
     max(DATE1) over (partition by Department) as MaxDate1, 
     max(DATE2) over (partition by Department, DATE1) as MaxDate2, 
     max(ID) over (partition by Department, DATE1, DATE2) as MaxID 
    from 
     employees 
    ) x 
where 
    x.DATE1 = x.MaxDate1 
    and x.DATE2 = x.MaxDate2 
    and x.ID = x.MaxID 
+0

Agradable, y bastante novedoso. Pero, ¿no solo usar row_number tendría menos sobrecarga? – MatBailie

+0

@Dems - Absolutamente lo haría. Quería darle otra forma de hacerlo si esto fuera solo un ejemplo y necesitara un control más granular. – Eric

+0

Gracias @Eric esta solución me ayudó. – jero

0

Algo así como ....

SELECT y2.* 
FROM 
(SELECT dept, 
    MAX(
    TO_CHAR(date1,'YYYYHH24MISS') || TO_CHAR(date2,'YYYYHH24MISS') 
    || id) as lastrec 
FROM yourtable y1 
GROUP BY dept) as ilv, 
yourtable y2 
WHERE y2.id=TO_NUMBER(SUBSTR(y2.lastrec, 21)) 
+1

Ohhh, lo entiendo. Pero asume que el campo ID es único, que no ha sido estado. Un buen pensamiento latteral sin embargo. – MatBailie

0
SELECT 
* 
FROM 
(
SELECT 
    Department, 
    Name, 
    Email, 
    ID, 
    DATE1, 
    DATE2, 
    max(DATE1) over (partition by Department) as MaxDate1, 
    max(DATE2) over (partition by Department, DATE1) as MaxDate2, 
    max(ID) over (partition by Department, DATE1, DATE2) as MaxID 
FROM 
    employees 
) 
WHERE 
x.DATE1 = x.MaxDate1 
AND x.DATE2 = x.MaxDate2 
AND x.ID = x.MaxID 
Cuestiones relacionadas