You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何筛选player_ratings表最高评分行,去重保留首行?

解决玩家最高评分去重问题

嘿,我明白你遇到的困扰了——你的查询确实能揪出每个玩家的最高评分,但当同一个玩家有好几条相同最高评分的记录时,所有匹配行都会被返回,没法只保留表中最上方的那一行。咱们调整下查询逻辑,轻松搞定这个问题!

问题根源

你原来用GROUP BY+JOIN的方式,先拿到每个玩家的最高评分,再关联回原表,这样所有等于最高评分的行都会被拉出来,自然会出现重复的玩家记录。要解决这个,我们得给每个玩家的评分记录排个序,只保留每组的第一条。

最优解决方案:使用窗口函数(推荐)

现在主流数据库(MySQL 8.0+、PostgreSQL、SQL Server等)都支持窗口函数,用ROW_NUMBER()就能精准实现需求:

SELECT player_id, rating
FROM (
    SELECT 
        player_id, 
        rating,
        -- 按玩家分组,评分降序排序,给每行分配唯一编号
        ROW_NUMBER() OVER (
            PARTITION BY player_id 
            ORDER BY rating DESC
            -- 如果你表中有主键、创建时间这类能明确行顺序的列,比如`id`,可以加上它确保排序稳定:
            -- ORDER BY rating DESC, id ASC
        ) AS row_num
    FROM player_ratings
) ranked_ratings
-- 只保留每组的第一行
WHERE row_num = 1
ORDER BY rating DESC;

这个查询的逻辑很清晰:

  1. 内层子查询给每个玩家的所有评分记录按评分降序分配编号,评分相同的记录会按数据库默认行顺序(或你指定的列)分配不同编号;
  2. 外层查询只筛选编号为1的行,这样每个玩家只会保留最高评分的第一条记录,完美解决重复问题。

兼容旧版本数据库的方案(比如MySQL 5.7及以下)

如果你的数据库不支持窗口函数,可以用关联子查询的方式替代:

SELECT pr.player_id, pr.rating
FROM player_ratings pr
WHERE NOT EXISTS (
    SELECT 1
    FROM player_ratings pr2
    WHERE pr2.player_id = pr.player_id
    AND (
        -- 排除存在更高评分,或评分相同但排在更前面的记录
        pr2.rating > pr.rating 
        OR (pr2.rating = pr.rating AND pr2.player_id < pr.player_id)
    )
)
ORDER BY pr.rating DESC;

不过这种写法的可读性和效率都不如窗口函数,优先推荐第一种方案。

最终效果

运行上面的查询后,就能得到你期望的结果:

player_idrating
1950
2850

内容的提问来源于stack exchange,提问作者leadingSkill

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:13:04