2010-04-17 58 views
20

Duplicar posible:
Retrieving the last record in each groupSQL: Busque el registro máximo por grupo

tengo una tabla, que tiene tres campos y datos.

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

deseo seleccionar el registro que tiene el valor más alto de Total para cada Name, por lo que mi resultado debe ser como este:

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

Probé grupo por orden de nombre por el total, pero se dan el récord más alto de grupo por resultado. ¿Alguien puede guiarme, por favor?

+3

I preguntarse cuántos duplicados hay para esta consulta, sin duda muchos m más que solo uno. Vea las más de 60 preguntas etiquetadas 'greatest-n-per-group' (para los casos n = 1). –

+0

@Jonathan: Esta es la "pregunta para siempre" en el campo de las preguntas SQL para principiantes. Hay uno nuevo todos los días en SO. – Tomalak

Respuesta

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

hola señor, gracias por su rápida respuesta. también he creado una consulta en este momento, y me da un resultado perfecto. aquí es mi consulta seleccione Nombre, Arriba, el total de animales en total en el grupo (SELECT MAX (total) FROM 'animals' grupo por su nombre) por su nombre mi pregunta es, que es más eficiente, la suya o mio cuando la tabla contiene 2 millones de datos? gracias de nuevo por su respuesta. – user319088

+0

¿Cuál es más eficiente? Defina los índices apropiados en su mesa y pruébelo. Aparte de eso, tu 'WHERE total en (...)' es incorrecto. Verás esto rápidamente una vez que lo intentes con * real * millones de registros y no solo con una mano llena. – Tomalak

+2

Es probable que la segunda consulta sea más eficiente que la primera porque la primera utiliza una subconsulta correlacionada que se puede ejecutar muchas veces en lugar de una sola vez en la segunda versión. –

5

Puede intentar algo así como

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 utilizando una cláusula EXISTS, cosa que vuelve la única fila que existe en ambas tablas

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

Esto funcionará, con la advertencia de que es costoso en tablas grandes con un optimizador ingenuo que no logra ejecutar la subconsulta correlacionada solo una vez. –

+1

@Jonathan +1 únicamente para usar el i diacrítico en "ingenuo". :-) – Tomalak