如何使用 SQL 从每个组中获得最高得分球员?
Posted
技术标签:
【中文标题】如何使用 SQL 从每个组中获得最高得分球员?【英文标题】:How to get max scoring player from each group using SQL? 【发布时间】:2020-02-11 13:46:15 【问题描述】:我有桌球员和比赛,我想找到得分最高的球员,请注意,如果得分匹配,则 ID 较低的球员是每个组的获胜者。
create table players (
player_id integer not null unique,
group_id integer not null
);
create table matches (
match_id integer not null unique,
first_player integer not null,
second_player integer not null,
first_score integer not null,
second_score integer not null
);
insert into players values(20, 2);
insert into players values(30, 1);
insert into players values(40, 3);
insert into players values(45, 1);
insert into players values(50, 2);
insert into players values(65, 1);
insert into matches values(1, 30, 45, 10, 12);
insert into matches values(2, 20, 50, 5, 5);
insert into matches values(13, 65, 45, 10, 10);
insert into matches values(5, 30, 65, 3, 15);
insert into matches values(42, 45, 65, 8, 4);
现在我想要结果
请注意,第一个和第二个玩家可以是同一组玩家。
结果:-
group_id | winner_id
----------+-----------
1 | 45
2 | 20
3 | 40
我不确定如何继续。
【问题讨论】:
【参考方案1】:以上都是正确的答案,只需提供所需的 90% 你可以在这里查看
https://www.db-fiddle.com/f/2Lp3LoMpXVefUbezRKBY3N/0
select group_id,player_id from
(
select
group_id
,P.player_id
,sum(points) as total
,DENSE_RANK () OVER (
PARTITION BY group_id
ORDER BY sum(points) desc, P.player_id asc
)P_Rank
from
(
select c.match_id, t.*
from matches c
cross join lateral (
values
(c.first_player, c.first_score),
(c.second_player, c.second_score)
) as t(player, points)
order by match_id, points
) base
right join players P
on base.player = P.player_id
group by 1,2
order by 1
)BT
where P_Rank=1
【讨论】:
【参考方案2】:SELECT GROUP_ID, PLAYER_ID, MAX_SCORE FROM (
SELECT GROUP_ID, PLAYER_ID, MAX_SCORE, DENSE_RANK() OVER(PARTITION BY GROUP_ID ORDER BY MAX_SCORE DESC,PLAYER_ID ASC) RANK
FROM
(
SELECT DISTINCT GROUP_ID, PLAYER_ID, COALESCE(MAX(TOT_SCORE)OVER (PARTITION BY PLAYER_ID),0)MAX_SCORE
FROM
(
SELECT PLAYER_ID, GROUP_ID, TOT_SCORE FROM
(
SELECT PLAYER, SUM(SCORE) AS TOT_SCORE
FROM
(
SELECT FIRST_PLAYER AS PLAYER,SUM(FIRST_SCORE)AS SCORE FROM MATCHES GROUP BY FIRST_PLAYER
UNION
SELECT SECOND_PLAYER AS PLAYER,SUM(SECOND_SCORE)AS SCORE FROM MATCHES GROUP BY SECOND_PLAYER
)
GROUP BY PLAYER
)S
RIGHT JOIN
PLAYERS P
ON
S.PLAYER=P.PLAYER_ID
))) WHERE RANK=1
【讨论】:
【参考方案3】:采取的方法:
对于表 2,我们将获得每个玩家的获胜者和相应分数 然后我们将玩家分组计算总和
上表将与表 1 连接后,将给出组中每个玩家的得分,我们将根据组和得分对这些数据进行排序
最后我们将选择每组的第一条记录,它将给出所需的结果
with actual_data as
(select row_number()over(partition by group_id
order by group_id asc,
coalesce(table2.sum_score, 0) desc) as rn,
group_id, player_id, coalesce(table2.sum_score, 0) as score
from players as table1
left join
(select player, sum(score) as sum_score from (
select match_id,
case
when first_score > second_score then first_player
when first_score = second_score and first_player < second_player
then first_player
else second_player end as player,
case
when first_score > second_score then first_score
when first_score = second_score and first_player < second_player
then first_score
else second_score end as score
from matches) as foo
group by player
order by sum_score desc) as table2
on table1.player_id = table2.player
order by group_id asc, coalesce(table2.sum_score, 0) desc
)
select group_id , player_id from actual_data where rn = 1
【讨论】:
【参考方案4】:我认为最简单的方法是横向连接和distinct on
:
select distinct on (p.group_id) p.group_id, v.player, v.score
from matches m cross join lateral
(values (first_player, first_score), (second_player, second_score)
) v(player, score) join
players p
on v.player = p.player_id
order by p.group_id, v.score desc;
Here 是一个 dbfiddle。
【讨论】:
【参考方案5】:使用row_number()
:
select group_id, player_id
from (
select
p.*,
row_number() over(
partition by p.group_id
order by case
when m.first_player = p.player_id then m.first_score
else m.second_score
end desc,
player_id
) rn
from players p
inner join matches m
on m.first_player = p.player_id or m.second_player = p.player_id
) x
where rn = 1
Demo on DB Fiddle:
| group_id | player_id |
| -------- | --------- |
| 1 | 65 |
| 2 | 20 |
注意:第 3 组只有一名玩家(player_id 40),他们没有参加任何比赛。
【讨论】:
没有 row_number > 返回值:+---+----+ | 1 | 65 | | 2 | 20 | +---+----+ @yan:第 3 组只有一名玩家(player_id 40),他们没有参加任何比赛。以上是关于如何使用 SQL 从每个组中获得最高得分球员?的主要内容,如果未能解决你的问题,请参考以下文章