解决mySQL中每个组的最大计分播放器

问题描述

请参考另一个堆栈溢出问题here,但是那里的答案不包括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,10);
insert into matches values(5,3,15);
insert into matches values(42,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 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
  ) 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

Demo on db-fiddle