在mySQL中求解每个组的最大得分球员

问题描述 投票:0回答:2

请参阅另一个 Stack Overflow 问题此处,但是那里的答案不包括 group_id 3 玩家。 我尝试在 MySQL 中复制答案,但我不熟悉 PostgreSQL。任何人都可以展示如何在 MySQL 中进行操作吗?

问题是返回每组中得分最高的玩家为

winner_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);

matches
桌子

match_id | first_player | second_player | first_score | second_score
  ----------+--------------+---------------+-------------+--------------
   1        | 30           | 45            | 10          | 12
   2        | 20           | 50            | 5           | 5
   13       | 65           | 45            | 10          | 10
   5        | 30           | 65            | 3           | 15
   42       | 45           | 65            | 8           | 4

预期产量

group_id | winner_id
  ----------+-----------
   1        | 45
   2        | 20
   3        | 40
mysql sql select greatest-n-per-group
2个回答
0
投票

我认为由于您无法使用其他问题的解决方案,因此您使用的是 MySQL 5.7 或更低版本。在这种情况下,您必须模拟

ROW_NUMBER/PARTITION
功能,您可以使用派生的每个玩家得分表中的
LEFT JOIN
来实现此功能,并加入比第一个表中的分数更大的
score
。任何在加入的表中没有更高分数的玩家显然具有最高分数。由于可能存在平局,因此我们从该表中取
player_id
值的最小值(当没有平局时,这没有效果)。

SELECT group_id, MIN(player_id) AS player_id
FROM (
  SELECT t1.group_id, t1.player_id
  FROM (
    SELECT p.player_id, p.group_id,
           SUM(CASE WHEN m.first_player = p.player_id THEN m.first_score
               ELSE m.second_score
               END) AS score
    FROM players p
    LEFT JOIN matches m ON m.first_player = p.player_id OR m.second_player = p.player_id
    GROUP BY p.player_id, p.group_id
  ) t1
  LEFT JOIN (
    SELECT p.player_id, p.group_id,
           SUM(CASE WHEN m.first_player = p.player_id THEN m.first_score
               ELSE m.second_score
               END) AS score
    FROM players p
    LEFT JOIN matches m ON m.first_player = p.player_id OR m.second_player = p.player_id
    GROUP BY p.player_id, p.group_id
  ) t2 ON t2.group_id = t1.group_id AND t2.score > t1.score
  GROUP BY t1.group_id, t1.player_id
  HAVING COUNT(t2.player_id) = 0
) w
GROUP BY group_id

输出:

group_id    player_id
1           45
2           20
3           40

db-fiddle 演示


0
投票
select group_id, player_id from (
select *, row_number() over(partition by A.group_id order by score DESC, player_id ASC) as ranking
from(
select player_id, group_id, sum(case when player_id=first_player then first_score 
                                else second_score end) as score
from players p
left join
matches m
on p.player_id=m.first_player or p.player_id=m.second_player
group by p.player_id, p.group_id)A)B
where B.ranking=1;

输出:

group_id | winner_id
  ----------+-----------
   1        | 45
   2        | 20
   3        | 40
© www.soinside.com 2019 - 2024. All rights reserved.