从MySQL中3列的每个组合中选择前2名得分者

从MySQL中3列的每个组合中选择前2名得分者,mysql,sql,database,performance,Mysql,Sql,Database,Performance,我有以下表格和数据: player_分数 +----+-----------+---------------------+-------+ |id |玩家| id |在|得分时创建|| +----+-----------+---------------------+-------+ | 1 | 1 | 2020-01-01 01:00:00 | 20 | | 2 | 1 | 2020-01-02 01:00:00 | 30 | | 3 |

我有以下表格和数据:

player_分数
+----+-----------+---------------------+-------+
|id |玩家| id |在|得分时创建||
+----+-----------+---------------------+-------+
|  1 |         1 | 2020-01-01 01:00:00 |    20 |
|  2 |         1 | 2020-01-02 01:00:00 |    30 |
|  3 |         2 | 2020-01-01 01:00:00 |    20 |
|  4 |         3 | 2020-01-01 01:00:00 |    20 |
|  5 |         4 | 2020-05-01 01:00:00 |    40 |
|  6 |         5 | 2020-01-02 01:00:00 |    20 |
|  7 |         6 | 2020-01-01 01:00:00 |    20 |
|  8 |         7 | 2020-01-03 01:00:00 |    20 |
|  9 |         1 | 2020-03-01 01:00:00 |    20 |
+----+-----------+---------------------+-------+
球员
+----+---------+-------------+----------+---------------------+---------+
|id |城市id |类别id |团体id |创建地点|名称|
+----+---------+-------------+----------+---------------------+---------+
|1 | 1 | 1 | 1 | 2020-01-01 01:00:00 |玩家1|
|2 | 1 | 2 | 1 | 2020-01-02 01:00:00 |玩家2|
|3 | 2 | 2 | 1 | 2020-01-01 01:00:00 |玩家3|
|4 | 2 | 1 | 1 | 2020-05-01 01:00:00 |玩家4|
|5 | 3 | 1 | 1 | 2020-01-02 01:00:00 |玩家5|
|6 | 4 | 2 | 1 | 2020-01-01 01:00:00 |玩家6|
|7 | 3 | 1 | 1 | 2020-01-01 01:00:00 |玩家7|
|8 | 4 | 2 | 1 | 2020-01-01 01:00:00 |玩家8|
+----+---------+-------------+----------+---------------------+---------+
城市
+----+------------+------------+
|id |国家| id |名称|
+----+------------+------------+
|1 | 1 |伦敦|
|2 | 2 |悉尼|
|3 | 2 |墨尔本|
|4 | 3 |多伦多|
+----+------------+------------+
国家
+----+-----------+
|id |名称|
+----+-----------+
|1 |英格兰|
|2 |澳大利亚|
|3 |加拿大|
+----+-----------+
类别
+----+------------+
|id |名称|
+----+------------+
|1 |第1类|
|2 |第2类|
+----+------------+
组
+----+---------+
|id |名称|
+----+---------+
|1 |第1组|
|2 |第2组|
+----+---------+
用于创建表和数据的SQL代码:

创建桌面播放器
(
id INT无符号自动递增主键,
城市id INT无符号非空,
类别\u id INT无符号非空,
组id INT无符号非空,
在DATETIME创建的\u不为空,
名称VARCHAR(255)不为空
);
创建桌上球员的分数
(
id INT无符号自动递增主键,
玩家id INT未签名非空,
在DATETIME创建的\u不为空,
分数INT(10)不为空
);
创建桌面城市
(
id INT无符号自动递增主键,
国家/地区id INT无符号非空,
名称VARCHAR(255)不为空
);
创建表格国家/地区
(
id INT无符号自动递增主键,
名称VARCHAR(255)不为空
);
创建表类别
(
id INT无符号自动递增主键,
名称VARCHAR(255)不为空
);
创建表“组”`
(
id INT无符号自动递增主键,
名称VARCHAR(255)不为空
);
将值(1,1,1,1,'2020-01-01 01:00:00,'Player1'),(2,1,2,1,'2020-01-02 01:00:00,'Player2'),(3,2,2,2,1,'2020-01-01-01 01:00:00,'Player3'),(4,2,1,1,1,'2020-05-01:00:00,'Player4'),(5,3,1,1,'2020-01-01:00:00,'Player5'),',(6,4,2,1,'2020-01-01 01:00:00,'Player6'),(7,3,1,1,'2020-01-01:00:00,'Player7'),(8,4,2,1,'2020-01-01:00:00,'Player8');
将值(1,1,'2020-01-01 01:00:00',20),(2,1,'2020-01-02 01:00:00',30),(3,2,'2020-01-01:00:00',20),(4,3,'2020-01-01-01:00',20),(5,4,'2020-05-01-01:00',40),(6,5,'2020-01-02-01-01:00',20),(7,2020-01-01-01:00',20)插入玩家分数中,(9, 1, '2020-03-01 01:00:00', 20);
在城市(id、国家/地区id、名称)中插入值(1,1,“伦敦”)、(2,2,“悉尼”)、(3,2,“墨尔本”)、(4,3,“多伦多”);
在国家(id,名称)中插入值(1,'England'),(2,'Australia'),(3,'Canada');
在类别(id、名称)中插入值(1,'Category 1'),(2,'Category 2');
在'groups'(id,name)中插入值(1,'group1'),(2,'group2');
“玩家”和“玩家分数”之间的关系是一对多的。而且,对于一些玩家来说,可能根本没有分数

我必须从每个国家、类别和组的组合中返回一份前2名得分手的列表。如果组合中没有得分,则不会为该组合选择任何得分手。如果组合中只有一名得分手,则只会选择一名得分手。如果一名球员没有任何得分,则不会选择该球员反恐执行局

如果组合中有两名或两名以上的玩家得分相同,则应选择最早创建的玩家(在“玩家”表中的字段中创建)

我使用MySQL 5.7,因此无法使用窗口函数!

因此,上述测试数据的结果应为:

+-----------+--------------+---------------+------------+---------------------+---------------------+--------------------------+
| player.id | country.name | category.name | group.name |  player.created_at  | player_scores.score | player_scores.created_at |
+-----------+--------------+---------------+------------+---------------------+---------------------+--------------------------+
|         1 | England      | Category 1    | Group 1    | 2020-01-01 01:00:00 |                  20 | 2020-03-01 01:00:00      |

|         2 | England      | Category 2    | Group 1    | 2020-01-02 01:00:00 |                  20 | 2020-01-01 01:00:00      |

|         3 | Australia    | Category 2    | Group 1    | 2020-01-01 01:00:00 |                  20 | 2020-01-01 01:00:00      |

|         4 | Australia    | Category 1    | Group 1    | 2020-05-01 01:00:00 |                  40 | 2020-05-01 01:00:00      |
|         7 | Australia    | Category 1    | Group 1    | 2020-01-01 01:00:00 |                  20 | 2020-01-03 01:00:00      |

|         6 | Canada       | Category 2    | Group 1    | 2020-01-01 01:00:00 |                  20 | 2020-01-01 01:00:00      |
+-----------+--------------+---------------+------------+---------------------+---------------------+--------------------------+
到目前为止,我有这个查询,但显然它离解决方案还很远。我尝试并搜索了一些提示,但到目前为止找不到任何提示:

SELECT players.*, player_scores.*, cities.*, countries.*, categories.*, groups.*
FROM players
LEFT JOIN cities
    ON players.city_id = cities.id
LEFT JOIN countries
    ON cities.country_id = country.id
LEFT JOIN categories
    ON players.category_id = categories.id
LEFT JOIN groups
    ON players.group_id = groups.id
LEFT JOIN player_scores
    ON player_scores.player_id = players.id
    AND player_scores.id IN (
        SELECT MAX(ps.id)
        FROM player_scores AS ps
        JOIN players AS p
            ON p.id = ps.player_id
        GROUP BY p.id
    )
INNER JOIN (
    SELECT DISTINCT countries.id, groups.id, categories.id
    FROM players
    LEFT JOIN cities
        ON players.city_id = cities.id
    LEFT JOIN countries
        ON cities.country_id = country.id
    LEFT JOIN groups
        ON players.group_id = groups.id
    LEFT JOIN categories
        ON players.category_id = categories.id
    INNER JOIN player_scores
        ON player_scores.player_id = players.id
    WHERE player_scores.id IN (
        SELECT MAX(ps.id)
        FROM player_scores AS ps
        JOIN players AS p
            ON p.id = ps.player_id
        GROUP BY p.id
    )
    GROUP BY countries.id, categories.id, groups.id
    HAVING MAX(player_scores.score) > 0
) players2 
    ON countries.id = players2.country_id 
    AND categories.id = players2.category_id 
    AND groups.id = players2.group_id;
我们将非常感谢您的帮助


更新:提供了测试数据和结果表。

总而言之,我是否认为这是中间结果,我们必须根据所述标准从中选择结果子集

SELECT p.name 
     , s.score
     , c.name city
     , x.name country
     , y.name category
     , g.name player_group
     , p.created_at
  FROM players p
  JOIN player_scores s
    ON s.player_id = p.id
  JOIN cities c
    ON c.id = p.city_id
  JOIN countries x
    ON x.id = c.country_id
  JOIN categories y
    ON y.id = p.category_id
  JOIN groups g
    ON g.id = p.group_id;
+---------+-------+-----------+-----------+------------+--------------+---------------------+
| name    | score | city      | country   | category   | player_group | created_at          |
+---------+-------+-----------+-----------+------------+--------------+---------------------+
| Player1 |    20 | London    | England   | Category 1 | Group 1      | 2020-01-01 01:00:00 |
| Player1 |    30 | London    | England   | Category 1 | Group 1      | 2020-01-01 01:00:00 |
| Player4 |    40 | Sydney    | Australia | Category 1 | Group 1      | 2020-05-01 01:00:00 |
| Player5 |    20 | Melbourne | Australia | Category 1 | Group 1      | 2020-01-02 01:00:00 |
| Player7 |    20 | Melbourne | Australia | Category 1 | Group 1      | 2020-01-01 01:00:00 |
| Player1 |    20 | London    | England   | Category 1 | Group 1      | 2020-01-01 01:00:00 |
| Player2 |    20 | London    | England   | Category 2 | Group 1      | 2020-01-02 01:00:00 |
| Player3 |    20 | Sydney    | Australia | Category 2 | Group 1      | 2020-01-01 01:00:00 |
| Player6 |    20 | Toronto   | Canada    | Category 2 | Group 1      | 2020-01-01 01:00:00 |
+---------+-------+-----------+-----------+------------+--------------+---------------------+

@我用测试更新了帖子data@Parfait如果可能的话,我想避免使用窗口函数。您拒绝使用窗口函数的原因是什么?@草莓,因为我使用的是较旧版本的MySQL。我无法为我正在处理的项目更新它。很公平,bu