我正在学习 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)