从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