2010-01-19 21 views
6

Encontré una pregunta que era muy similar a esta, pero que utilizaba características que parecen exclusivas de Oracle. Estoy buscando hacer esto en SQL Server.Obtener la fila que tiene el valor Máx. Para una columna en SQL Server

tengo una tabla como la siguiente:

MyTable 
-------------------- 
MyTableID INT PK 
UserID  INT 
Counter INT 

Cada usuario puede tener múltiples filas, con diferentes valores para Counter en cada fila. Necesito encontrar las filas con el valor más alto Counter para cada usuario.

¿Cómo puedo hacer esto en SQL Server 2005?

Lo mejor que se me ocurre es una consulta devuelve el MAX(Counter) para cada UserID, pero necesito toda la fila debido a otros datos en esta tabla que no se muestran en la definición de mi tabla por simplicidad.

EDIT: Algunas de las respuestas en esta publicación me han llamado la atención, me olvidé de un detalle importante. Es posible tener más de 2 filas donde un ID de usuario puede tener el mismo valor de contador MAX. Ejemplo a continuación actualizado para saber cuál será el dato/resultado esperado.

Con estos datos:

MyTableID UserID Counter 
--------- ------- -------- 
1   1   4 
2   1   7 
3   4   3 
4   11  9 
5   11  3 
6   4   6 
... 
9   11  9 

Quiero que estos resultados para los valores máximo duplicados, seleccionar la primera aparición en el orden del servidor SQL los selecciona. Las filas que se devuelven no es importante en este caso, siempre que el ID de usuario/Contador pares son distintos:

MyTableID UserID Counter 
--------- ------- -------- 
2   1   7 
4   11  9 
6   4   6 

Respuesta

9

me gusta usar una expresión de tabla común para ese caso, con una ROW_NUMBER adecuado() en i t:

WITH MaxPerUser AS 
(
    SELECT 
    MyTableID, UserID, Counter, 
    ROW_NUMBER() OVER(PARTITION BY userid ORDER BY Counter DESC) AS 'RowNumber' 
    FROM dbo.MyTable 
) 
SELECT MyTableID, UserID, Counter 
FROM MaxPerUser 
WHERE RowNumber = 1 

que divide los datos a través de la identificación de usuario, órdenes que por el contador (descendente) para cada usuario, y luego las etiquetas de cada una de las filas empezando con 1 para cada usuario. Seleccione solo aquellas filas con un 1 para rownumber y tendrá su máximo. valores por usuario.

Es así de fácil :-) Y consigo resultados algo como esto:

MyTableID UserID Counter 
    2   1  7 
    6   4  6 
    4   11  9 

Sólo una entrada por el usuario, independientemente del número de filas por el usuario pasará a tener el mismo valor máximo.

+3

@marc_s: Voto en serie: eres el tercero que he visto, incluido yo mismo. –

+0

@OMGPonies: sí, supongo ... Lo entiendo en una pieza obstinada, o cuando tienes un error flagrante en tu publicación ...... de todos modos ... –

+1

@marc_s: +1: Every de vez en cuando sucede en preguntas de SQL. –

0

Hay varias maneras de hacer esto, echar un vistazo a esta Including an Aggregated Column's Related Values Varios métodos se muestran incluyendo el desempeño diferencias

Aquí es una función de ejemplo

select t1.* 
from(
select UserID, max(counter) as MaxCount 
from MyTable 
group by UserID) t2 
join MyTable t1 on t2.UserID =t1.UserID 
and t1.counter = t2.counter 
+0

¿Qué sucede en el caso cuando tiene el mismo usuario que tiene 2 recuentos iguales? –

0
select m.* 
from MyTable m 
inner join (
    select UserID, max(Counter) as MaxCounter 
    from MyTable 
    group by UserID 
) mm on m.UserID = mm.UserID and m.Counter = mm.MaxCounter 
+0

¿Qué sucede en el caso cuando tiene el mismo usuario que tiene 2 recuentos iguales? –

+0

Eso tiene que ser 'y m.Contador == mm.MaxCounter' de lo contrario obtendrá un error –

+0

Sí, error de escritura, reparado. – RedFilter

0

Pruebe esto ... Estoy bastante seguro de que esta es la única manera de asegurarse realmente de obtener una fila por Usuario.

SELECT MT.* 
FROM MyTable MT 
    INNER JOIN (
     SELECT MAX(MID.MyTableId) AS MaxMyTableId, 
      MID.UserId 
     FROM MyTable MID 
      INNER JOIN (
       SELECT MAX(Counter) AS MaxCounter, UserId 
       FROM MyTable 
       GROUP BY UserId 
      ) AS MC 
       ON (MID.UserId = MC.UserId 
        AND MID.Counter = MC.MaxCounter) 
     GROUP BY MID.UserId 
    ) AS MID 
     ON (MID.UserId = MC.UserId 
      AND MID.MyTableId = MC.MaxMyTableId) 
+0

Tiene bastantes problemas en esta consulta con nombres de columnas ambiguos y otras cosas ... –

+0

ya lo escribí rápidamente ... pero la idea funciona. Lo arreglaré. – anthonyv

2

Creo que esto te ayudará.

SELECT distinct(a.userid), MAX(a.counterid) as counterid 
FROM mytable a INNER JOIN mytable b ON a.mytableid = b.mytableid 
GROUP BY a.userid 
+3

No hay necesidad de 'distinct'. Un 'group by' hará eso automáticamente. – Ben

+0

Esto hizo el truco para mí, gracias, pero ¿cómo funciona? – zzapper

Cuestiones relacionadas