2010-04-17 40 views
20

Eventuali duplicati:
Retrieving the last record in each groupSQL: Trovare il record max per gruppo

ho una tabella, che ha tre campi e dei dati.

 
Name , Top , Total 
cat , 1 , 10 
dog , 2 ,  7 
cat , 3 , 20 
horse , 4 ,  4 
cat , 5 , 10 
dog , 6 ,  9 

voglio selezionare il record che ha maggior valore ai Total per ogni Name, quindi il mio risultato dovrebbe essere simile a questo:

 
Name , Top , Total 
cat , 3 , 20 
horse , 4 ,  4 
Dog , 6 ,  9 

Ho cercato di gruppo per Nome ordina totale, ma dare in cima alla maggior parte dei record di gruppo in base al risultato. Qualcuno può guidarmi, per favore?

+3

I chiedo quanti duplicati ci sono per questa query - sicuramente molti m più di uno solo. Vedi le oltre 60 domande taggate "greatest-n-per-group" (per i casi n = 1). –

+0

@ Jonathan: Questa è la "domanda per sempre" nel campo delle domande per principianti SQL. Ce n'è uno ogni giorno su SO. – Tomalak

risposta

27
select 
    Name, Top, Total 
from 
    sometable 
where 
    Total = (select max(Total) from sometable i where i.Name = sometable.Name) 

o

select 
    Name, Top, Total 
from 
    sometable 
    inner join (
    select max(Total) Total, Name 
    from sometable 
    group by Name 
) as max on max.Name = sometable.Name and max.Total = sometable.Total 
+0

ciao signore, grazie per la vostra risposta rapida. Ho anche creato una query proprio ora, e mi sta dando un risultato perfetto. qui è la mia domanda selezionare Nome, Top, totale da animali dove totale (SELECT max (totale) DA 'animali d'gruppo per nome) del gruppo per nome La mia domanda è, che è più efficiente, il vostro o mio quando la tabella contiene 2 milioni di dati? grazie ancora per la risposta. – user319088

+0

Quale è più efficiente? Definisci gli indici appropriati sul tuo tavolo e provalo. A parte questo, il tuo valore 'WHERE in (...)' è sbagliato. Lo vedresti rapidamente una volta provato con * effettivi * milioni di record e non solo con una mano piena. – Tomalak

+2

È probabile che la seconda query sia più efficiente della prima poiché la prima utilizza una sottoquery correlata che potrebbe essere eseguita molte volte anziché una sola volta nella seconda versione. –

5

Si può provare qualcosa di simile

SELECT s.* 
FROM sometable s INNER JOIN 
     (
      SELECT Name, 
        MAX(Total) MTotal 
      FROM sometable 
      GROUP BY Name 
     ) sMax ON s.Name = sMax.Name 
       AND s.Total = sMax.MTotal 
0

o utilizzando una clausola EXISTS, wich restituisce l'unica riga che esiste in entrambe le tabelle

SELECT * from sometable T 
where exists 
(select 1 
from (SELECT nombre, max(total) as total FROM sometable TT 
    GROUP by nombre) TT 
where T.name=TT.name 
and T.total=TT.total 
) 
+1

Questo funzionerà, con l'avvertenza che è costoso su grandi tabelle con un ottimizzatore ingenuo che non riesce ad eseguire la sub-query correlata solo una volta. –

+1

@Jonathan +1 esclusivamente per l'uso del diacritico i in "naïve". :-) – Tomalak