2012-01-09 17 views
6

Ho questa tabella:Oracle SQL: ottenere solo una riga max usando criteri multipli

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 

voglio ottenere la riga (solo uno per reparto) con max DATE1, ma non è unico nel suo genere! Quindi se ci sono più risultati voglio ottenere il massimo DATE2, e se ce ne sono più di uno allora viene restituito quello con l'ID più grande.

Quindi c'è risultato della query sarebbe:

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

Grazie mille.

risposta

18

è necessario utilizzare la funzione 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

il suono grande! funziona per una partizione di più colonne? perché la mia tabella è molto più complicata – jllopezpino

+0

@ user337746 - Sì, 'partition by' funziona esattamente come fa un'istruzione' group by'. – Eric

+0

sì, partizione di è simile alla clausola group by ma per la funzione Row_Number –

5

utilizzare la clausola 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

Bello e carino. Ma non usare solo row_number avrebbe meno costi generali? – MatBailie

+0

@Dems - Assolutamente lo sarebbe. Volevo dare un altro modo per farlo se questo fosse solo un esempio e avesse bisogno di un controllo più granulare. – Eric

+0

Grazie a @Eric questa soluzione mi ha aiutato. – jero

0

Qualcosa di simile ....

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, ho capito. Ma presume che il campo ID sia unico, che non è stato stato. Bel pensiero posteriore però. – 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 
Problemi correlati