2010-01-19 130 views
6

我发现一个与此类似的问题,但使用了Oracle似乎专有的功能。我期待在SQL Server中执行此操作。获取具有SQL Server中列最大值的行

我有一个表是这样的:

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

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

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

我可以拿出最好的查询返回MAX(Counter)为每个UserID,但我需要整行,因为这个表中的其他数据没有显示在我的表定义为简单起见。

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

有了这些数据:

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服务器选择他们第一次出现。返回的行是在这种情况下并不重要,只要用户名/计数器对是不同的:

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

回答

9

我喜欢用一个公共表表达式为这种情况下,与合适的ROW_NUMBER()函数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 

即划分在用户ID中的数据,命令它由计数器(降序)对于每个用户,然后标记每个行的从1开始为每个用户。只选择那些行数为1的行,并且你有最大值。每个用户的价值。

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

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

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

+3

@marc_s:串行downvoter - 你是我见过的第三个,包括我自己。 – 2010-01-19 22:20:23

+0

@OMGPonies:是的,我想......我明白这是一篇自以为是的评论,或者当你在帖子中有一个明显的错误...... anyhoo ..... – 2010-01-19 22:21:13

+1

@marc_s:+1:Every现在,然后它发生在SQL问题。 – 2010-01-19 22:25:23

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 
+0

如果您拥有2个相同的用户相同的用户,那么会发生什么? – 2010-01-19 22:15:15

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

如果您拥有2个相同的用户,则会发生什么情况? – 2010-01-19 22:16:27

+0

这需要'和m.Counter == mm.MaxCounter',否则你会得到一个错误 – 2010-01-19 22:23:43

+0

是的,错字,固定。 – RedFilter 2010-01-19 22:40:55

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) 
+0

这个查询中有很多问题,列名和其他东西不明确...... – 2010-01-19 22:25:27

+0

你我很快就写下了...但这个想法很有效。我会解决它。 – anthonyv 2010-01-19 22:30:03

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 
+3

不需要'distinct'。一个'group by'会自动完成。 – Ben 2012-05-06 12:55:53

+0

这对我来说有窍门,但它是如何工作的? – zzapper 2013-10-24 08:03:37