获取SQL Server中具有Max值的行

时间:2010-01-19 22:02:29

标签: sql sql-server sql-server-2005

我发现了一个与此问题非常相似的问题,但使用了Oracle独有的功能。我希望在SQL Server中执行此操作。

我有一张这样的表:

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

每个用户可以有多行,每行中Counter的值不同。我需要找到每个用户具有最高Counter值的行。

如何在SQL Server 2005中执行此操作?

我能想到的最好的是一个查询,为每个MAX(Counter)返回UserID,但我需要整行,因为此表中的其他数据未在我的表定义中显示,以简化缘故。

编辑:我在这篇文章的一些答案中引起了我的注意,我忘记了一个重要的细节。可以有2+行,其中UserID可以具有相同的MAX计数器值。下面的示例更新了预期的数据/输出应该是什么。

有了这些数据:

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

我想要重复MAX值的这些结果,选择SQL Server选择它们的任何顺序的第一次出现。在这种情况下返回哪些行并不重要,只要UserID / Counter对是不同的:

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

5 个答案:

答案 0 :(得分:9)

我喜欢在这种情况下使用公用表表达式,其中包含一个合适的ROW_NUMBER()函数:

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

通过UserID对数据进行分区,按计数器(降序)为每个用户排序,然后为每个用户标记以1开头的每一行。只选择rownumber为1的那些行,并且你有最大值。每个用户的价值。

就这么简单:-)我得到的结果是这样的:

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

每个用户只有一个条目,无论每个用户有多少行具有相同的最大值。

答案 1 :(得分:2)

我认为这会对你有帮助。

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

答案 2 :(得分:0)

有几种方法可以做到这一点,看看这个Including an Aggregated Column's Related Values显示了几种方法,包括性能差异

这是一个例子

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

答案 3 :(得分: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

答案 4 :(得分:0)

试试这个...我很确定这是真正确保每个用户获得一行的唯一方法。

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)