如何用SQL添加每个游戏最高分玩家列(无需JOIN操作)
用SQL窗口函数实现需求:为每行添加对应游戏的最佳玩家
当然可以!用SQL的**窗口函数(分析函数)**完全能满足你的需求——不用JOIN,也不会丢失任何一行数据。我结合常见的游戏得分场景给你详细说明:
先假设你的数据结构
咱们先拿一张典型的游戏得分表 game_scores 举例,表结构和数据大概是这样:
| game_id | player_name | score |
|---|---|---|
| 1 | Alice | 85 |
| 1 | Bob | 92 |
| 1 | Charlie | 92 |
| 2 | Dave | 78 |
| 2 | Eve | 88 |
这里游戏1有两个玩家(Bob和Charlie)得分都是最高分92,所以我会顺便讲下怎么处理并列的情况。
方法1:用 FIRST_VALUE() 快速获取最佳玩家
FIRST_VALUE() 是个很实用的窗口函数,它能在每个分组(这里就是每场游戏)里,按照你指定的排序规则取出第一个值。我们按游戏分组,再按得分降序排序,就能拿到每场游戏的最高分玩家:
SELECT game_id, player_name, score, FIRST_VALUE(player_name) OVER ( PARTITION BY game_id ORDER BY score DESC, player_name ASC -- 得分相同时按玩家名排序,保证结果稳定 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING -- 确保取整个游戏分组里的第一个值 ) AS best_player FROM game_scores;
执行结果
跑这个查询后,所有原数据行都会保留,同时best_player列会显示对应游戏的最高分玩家:
| game_id | player_name | score | best_player |
|---|---|---|---|
| 1 | Bob | 92 | Bob |
| 1 | Charlie | 92 | Bob |
| 1 | Alice | 85 | Bob |
| 2 | Eve | 88 | Eve |
| 2 | Dave | 78 | Eve |
如果你的业务需要显示所有并列的最高分玩家(比如游戏1里要同时显示Bob和Charlie),可以用STRING_AGG()结合窗口函数(适用于PostgreSQL、SQL Server等支持的数据库):
SELECT game_id, player_name, score, STRING_AGG(player_name, ', ') OVER ( PARTITION BY game_id ORDER BY score DESC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) AS best_players FROM game_scores QUALIFY score = MAX(score) OVER (PARTITION BY game_id);
(注:如果你的数据库不支持QUALIFY,可以把逻辑放到子查询里过滤)
方法2:用 MAX() 窗口函数+条件判断
另一种思路是先算出每场游戏的最高分,再通过条件匹配找到对应的玩家。如果只想在得分等于最高分的行显示玩家名,其他行留空,可以这么写:
SELECT game_id, player_name, score, CASE WHEN score = MAX(score) OVER (PARTITION BY game_id) THEN player_name ELSE NULL END AS best_player FROM game_scores;
要是想让所有行都显示对应游戏的最佳玩家,可以把CASE和MAX()窗口函数嵌套起来:
SELECT game_id, player_name, score, MAX(CASE WHEN score = MAX(score) OVER (PARTITION BY game_id) THEN player_name END) OVER (PARTITION BY game_id) AS best_player FROM game_scores;
这个写法如果有并列最高分玩家,会取字典序最大的那个(比如游戏1里会显示Charlie)。
核心知识点
- PARTITION BY game_id:这是关键,它确保我们是按每场游戏单独计算最高分,而不是全局统计
- 窗口函数的优势:直接在原表的每行上计算分组结果,不用做JOIN,自然不会丢失任何数据行
- 并列情况处理:根据你的业务需求,选择取第一个玩家、合并所有并列玩家,还是取字典序最大的玩家即可
内容的提问来源于stack exchange,提问作者Adam Black
相关产品推荐
相关产品推荐

