找到每个阶段的获胜者

1 sql-server sql-server-2014

我正在学习 SQL,我正在努力找一份工作。我在 MS SQL Server 2014 中有下表:

该表名为 Game,具有以下字段:Name、Stage #、Score。

我的目标是用他/她的名字写出每个阶段的获胜者(阶段的获胜者是获得最高分的人)。

这是原始表:

Name    Stage #         Score
George     A              10
Joe        A              10
Pete       A               9
Jane       B               7
Sally      B               6
Run Code Online (Sandbox Code Playgroud)

输出应该如下所示:

Winner Name    Score         Stage
George           10             A
Joe              10             A
Jane              7             B
Run Code Online (Sandbox Code Playgroud)

我怎样才能完成这个任务?一位同事向我推荐了http://sqlfiddle.com/以帮助我解决这个问题,但该网站显然不适用于 MS SQL Server 2014 或 MS SQL Server 2008。因此,我可以在这里获得一些帮助吗?

我了解一些基本功能,例如 SELECT、WHERE、GROUP BY、JOIN 和 HAVING,但我无法将它们放在一起以获得我想要的正确的三行输出。

ype*_*eᵀᴹ 11

在 SQL 中有数十种不同的方法可以做到这一点。让我们从简单的相关子查询开始(记住这个花哨的名字,一旦你看到并写下其中的几个,它们就很容易理解):

select                                -- show
    g.name, g.stage, g.score          -- all data
from                                  -- from
    game as g                         -- the table
where                                 -- where
    not exists                        -- there isn't
        ( select *                    -- any other 
          from game as g2             -- from the same table
          where g2.stage = g.stage    -- and the same stage
            and g2.score > g.score    -- with bigger score
        ) ;
Run Code Online (Sandbox Code Playgroud)

另一种简单的方法是首先使用GROUP BY(在子查询中,派生表或 CTE)找到每个阶段的最大分数,然后JOIN返回到原始表:

-- using derived table
select      
    g.name, g.stage, g.score 
from      
    game as g 
  join
    ( select stage, max(score) as score
      from game
      group by stage
    ) as m
  on  m.stage = g.stage
  and m.score = g.score ;

-- using CTE
with stage_max as
    ( select stage, max(score) as score
      from game
      group by stage
    ) 
select      
    g.name, g.stage, g.score 
from      
    game as g 
  join
    stage_max as m
  on  m.stage = g.stage
  and m.score = g.score ;
Run Code Online (Sandbox Code Playgroud)

更现代的方法是使用窗口函数(在您的 SQL Server 版本中可用),即RANK()函数,因此首先您获得每个阶段每个人的“排名”,然后仅选择带有rank=1. 这也可以通过派生表或 CTE 来完成:

-- window functions, using derived table
select      
    w.name, w.stage, w.score 
from      
    ( select name, stage, score,
             rnk = rank() over (partition by stage
                                order by score desc)
      from game
    ) as w
where
    w.rnk = 1 ;

-- window functions, using CTE
with ranking as
    ( select name, stage, score,
             rnk = rank() over (partition by stage
                                order by score desc)
      from game
    ) 
select      
    w.name, w.stage, w.score 
from      
    ranking as w 
where
    w.rnk = 1 ;
Run Code Online (Sandbox Code Playgroud)