2012-10-31 7 views
8

Sto cercando di selezionare solo la riga con il più alto seq per ogni IDcome selezionare solo la riga con la sequenza massima senza utilizzare una sottoquery?

ID | Seq | Age 
------------------- 
A  1  20 
A  2  30 
B  1  25 
B  2  32 
B  3  44 
B  4  48 
C  1  11 

Questo sembra funzionare

SELECT ID, Age 
FROM Persons a 
WHERE Seq = (SELECT MAX(Seq) FROM Persons b WHERE a.ID = b.ID) 

Ma è questo il modo migliore, l'unico modo? Non mi piace usare le subquery se non devo e ricordo che puoi usare qualcosa ma ho dimenticato di cosa si tratta. Qualche idea?

+0

Cosa rdbms stai usando? –

+0

Principalmente SQL Server, ma se è oracle compatibile, allora è fantastico – jenswirf

+0

Il mio approccio 'ROW_NUMBER' funziona anche in Oracle, come ho provato con SQl-Fiddle. Dai un'occhiata al link nella mia risposta. –

risposta

5

Supponendo SQL-Server (> = 2005) o Oracle (10g?):

WITH CTE AS 
( 
    SELECT 
     ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Seq DESC) AS RN 
     , ID, Age 
    FROM 
     Persons 
) 
SELECT ID, Age 
FROM CTE 
WHERE RN = 1 

ROW_NUMBER restituisce il numero sequenziale di una riga all'interno di una partizione di un set di risultati.

Edit: funziona anche in Oracle come potete vedere qui: http://sqlfiddle.com/#!4/b7e79/2/0

+0

grazie per aver rinfrescato il mio cervello, l'ho usato in passato e ora lo uso dopo molto tempo, funziona perfettamente! – superachu

1

In generale, si neeed di utilizzare le funzioni di ranking a finestre o - Rank(), Row_number(), ecc

select * 
from 
(
    select *, row_number() over (partition by id order by age desc) rn 
    from yourtable 
) v 
where rn = 1 

Questa volontà funziona in SQL Server 2005+: in Oracle potrebbe essere necessario specificare i nomi dei campi in modo esplicito, anziché *

+0

Questo è il modo migliore in cui avrei potuto pensare. Tuttavia, ci sono due clausole di selezione in esso, e se non ti piace, puoi semplicemente prendere la selezione interiore e nella tua app segare tutto ciò che non è classificato 1;) – OzrenTkalcecKrznaric

1

Jus t nel caso in cui si utilizza un RDBMS che non supporta funzioni finestra, è possibile utilizzare:

SELECT Persons.ID, Persons.Age, Persons.Seq 
FROM Persons 
     INNER JOIN 
     ( SELECT Persons.ID, MAX(Seq) AS Seq 
      FROM Persons 
      GROUP BY Persons.ID 
     ) MaxP 
      ON MaxP.ID = Persons.ID 
      AND MaxP.Seq = Persons.Seq 

Si tratta ancora una sottoquery, ma non vedo un modo di fare questo senza uno, né ho davvero capisci perché vorresti evitarli

Problemi correlati