PostgreSQL上的这个问题现在困扰着我很长时间。我尝试了一下,搜寻了所有可能但无法结束的结果,该结果将第3组的玩家考虑在内。因此,即使这个问题可能是重复的,也找不到正确的答案。希望有帮助。
问题如下:编写一个SQL查询,该查询返回一个包含每个组中获胜者的表。每条记录均应包含该组的ID和该组中获胜者的ID(来自同一组的玩家竞争)。记录应通过增加组的ID号来排序,如果出现平局,则ID最低的玩家获胜。
给出此模式:
玩家:
+-------------+-------+
| Column Name | Type |
+-------------+-------+
| player_id | int |
| group_id | int |
+-------------+-------+
匹配项:
+---------------+---------+
| Column Name | Type |
+---------------+---------+
| match_id | int |
| first_player | int |
| second_player | int |
| first_score | int |
| second_score | int |
+---------------+---------+
对于以下示例:
玩家表:
+-----------+------------+
| player_id | group_id |
+-----------+------------+
| 20 | 2 |
| 30 | 1 |
| 40 | 3 |
| 45 | 1 |
| 50 | 2 |
| 40 | 1 |
+-----------+------------+
比赛表:
+------------+--------------+---------------+-------------+--------------+
| match_id | first_player | second_player | first_score | second_score |
+------------+--------------+---------------+-------------+--------------+
| 1 | 30 | 45 | 10 | 12 |
| 2 | 20 | 50 | 5 | 5 |
| 3 | 65 | 45 | 10 | 10 |
| 4 | 30 | 65 | 3 | 15 |
| 5 | 45 | 65 | 8 | 4 |
+------------+--------------+---------------+-------------+--------------+
您的查询应返回:
+-----------+------------+------------+
| group_id | winner_id | tot_score |
+-----------+------------+------------+
| 1 | 45 | 30 |
| 2 | 20 | 5 |
| 3 | 40 | 0 |
+-----------+------------+------------+
第1组中,玩家45分得分最高。在第2组中,两个玩家均获得5分,但玩家20的ID较低,因此他是获胜者。在小组3中,只有一名球员,尽管他没有参加任何比赛,但他是获胜者。
到目前为止,设法做到的最好的方法是(在PostgreSQL上:
SELECT group_id, player_id, score
FROM
(
SELECT sq2.player_id, p.group_id, sq2.score,
RANK() OVER (PARTITION BY p.group_id ORDER BY score DESC) as position
FROM
(
SELECT player_id, SUM(score) score
FROM (
SELECT first_player as player_id, first_score as score FROM matches
UNION ALL
SELECT second_player as player_id, second_score as score FROM matches
) as sq1
GROUP BY player_id
) as sq2
right join players p
on p.player_id = sq2.player_id
) as sq3
WHERE position = 1 order by group_id, player_id
输出哪个:
+-----------+-----------------------+------------+
| group_id | player_id | score |
+-----------+-----------------------+------------+
| 1 | 45 | 30 |
| 2 | 20 | 5 |
| 2 | 50 | 5 |
| 3 | [NULL](instead of 40) | [NULL] (should be 0)|
+-----------+-----------------------+------------+
您能否帮助生成具有完整正确结果的查询? (以及第3组玩家的详细信息)
还想知道为什么查询会在player_id中为正确的连接返回NULL。感谢帮助!
*这个问题显然也是Leetcode.com上的一个问题,称为“锦标赛冠军” *
您可以如下使用distinct on
和聚合:
select distinct on (p.group_id)
p.group_id,
player_id winner_id,
coalesce(sum(first_score) filter(where p.player_id = m.first_player), 0)
+ coalesce(sum(second_score) filter(where p.player_id = m.second_player), 0)
tot_score
from players p
left join matches m on p.player_id in (m.first_player, m.second_player)
group by p.group_id, p.player_id
order by p.group_id, tot_score desc, p.player_id
group_id | winner_id | tot_score-------:| --------:| --------:1 | 45 | 302 | 20 | 53 | 40 | 0