SQL Query,获得最大值而不重复

时间:2013-09-03 15:55:16

标签: sql sql-server sql-server-2008

我有两张桌子,Player和Shot。 Player和Shot之间存在1对多的关系。我想获得一些玩家信息,比如Email,FirstName和LastName,以及玩家的头号信息,其中包含各种部分 - CalculatedScore,AccuracyScore,DistanceScore和TimeScore。 CalculatedScore是最重要的值。所有其他都是该分数的组成部分。

这是我的最大努力:

<!-- language: lang-sql -->
select s_max.PlayerId as playerId_max, s_max.TopScore, s.PlayerId, p.FirstName,
p.LastName, s.CalculatedScore, s.AccuracyScore, s.TimeScore, s.DistanceScore from Player p
inner join Shot s on s.PlayerId = p.Id
inner join (
    select distinct MAX(CalculatedScore) over (partition by PlayerId) as TopScore,
     PlayerId from Shot s2  
) s_max on s.PlayerId = s_max.PlayerId and s.CalculatedScore = s_max.TopScore
order by PlayerId desc

这与我需要的几乎完全相同,但它会返回与最高分相关的每一行。让它返回一行却令人惊讶地令人沮丧。

感谢您的时间。

4 个答案:

答案 0 :(得分:1)

如果我理解正确,这就是你想要的:

;WITH CTE AS
(
    SELECT  *,
            RN=ROW_NUMBER() OVER(PARTITION BY PlayerId 
                                 ORDER BY CalculatedScore DESC)
    FROM Shot
)
SELECT  A.PlayerId as playerId_max, 
        B.TopScore, 
        A.FirstName,
        A.LastName, 
        B.CalculatedScore, 
        B.AccuracyScore, 
        B.TimeScore, 
        B.DistanceScore
FROM Player A
INNER JOIN CTE B
    ON A.PlayerId = B.PlayerId
WHERE B.RN = 1

答案 1 :(得分:1)

您可以使用row_number()代替(获得一行)。此外,使用窗口函数时不需要额外的连接:

select s.PlayerId , s.TopScore, s.PlayerId, p.FirstName,
       p.LastName, s.CalculatedScore, s.AccuracyScore, s.TimeScore, s.DistanceScore
from Player p inner join
     (select s.*,
             row_number() over (partition by s.PleryId order by CalculatedScore desc
                               ) as seqnum
      from Shot s
     ) s
     on s.PlayerId = p.Id and seqnum = 1
order by s.PlayerId desc

答案 2 :(得分:1)

我认为这是使用outer/cross apply的好例子。这应该比使用窗口函数更好,特别是如果Player表的行数很少:

select
    p.Id, p.FirstName, p.LastName,
    s.CalculatedScore, s.AccuracyScore, s.TimeScore, s.DistanceScore
from Player as p
    outer apply (
        select top 1 s.*
        from Shot as s
        where s.PlayerId = p.Id
        order by s.CalculatedScore desc
    ) as s

这里有sql fiddle demo示例,您可以查看效果。

答案 3 :(得分:0)

您可以使用ROW_NUMBER()功能:

SELECT *
FROM (select   s_max.PlayerId as playerId_max
             , s_max.TopScore
             , s.PlayerId
             , p.FirstName
             , p.LastName
             , s.CalculatedScore
             , s.AccuracyScore
             , s.TimeScore
             , s.DistanceScore
             , ROW_NUMBER() OVER(PARTITION BY PlayerID ORDER BY CalculatedScore DESC)'RowRank'
        from Player p
        inner join Shot s 
            on s.PlayerId = p.Id
        order by PlayerId desc
        )sub
WHERE RowRank = 1