【问题标题】:Rank over partition and group by column, how can I do it?对分区和按列分组,我该怎么做?
【发布时间】:2021-06-21 23:57:42
【问题描述】:

我有一个包含玩家结果/分数的数据库表。 数据如下所示:

player_id result_date score game_type
1 2020-03-01 154 1
2 2020-03-15 171 2
3 2020-03-15 122 1
2 2020-03-17 210 2
1 2020-04-01 190 2
2 2020-05-15 125 1
1 2020-06-01 167 1
2 2020-06-10 173 1

我想获得每种游戏类型的前三名玩家,并且还能够过滤日期,但我不知道该怎么做。

目前我的查询如下所示:

SELECT rr.* FROM 
(SELECT game_type, player_id, result_date, score,
RANK() OVER (partition by game_type ORDER BY score DESC) as game_rank
FROM results
WHERE result_date >= '2020-01-01') rr
HAVING game_rank <= 3;

但是同一个玩家可以多次排名。 我只想要每个游戏类型的每个玩家的最高分。我该怎么做?

数据库是Mysql 8.0。

【问题讨论】:

  • 但是同一个玩家可以多次排名。我只想要每种游戏类型的每个玩家的最佳分数。 某些玩家的某些分数可能不是该玩家的最佳分数,而是游戏的最佳分数...您的算法不允许输出此播放器。有可能某些玩家在 2 场比赛中是最好的 - 您的算法不允许了解该球员必须返回哪个游戏。
  • @Akina:看来你对这部分有误解。照原样,玩家可以同时在一种游戏类型中排名前 1、第 2 和第 3,但 frofrik 只想要他们一次(以他们在游戏类型中的最高分)。
  • @ThorstenKettner 如果是这样,那么第一步很简单GROUP BY player,game 并得到MAX(score)。然后排名并获得前 3 名。
  • @Akina:是的。 GROUP BY player_id, game_type 就是这样。如果您想要整行,请改用PARTITION BY player_id, game_typeROW_NUMBER。这就是我在回答中所做的。

标签: mysql sql database mysql-8.0


【解决方案1】:

你需要两个步骤:

  1. 按游戏类型和玩家获得最高分。
  2. 从中获得每种游戏类型得分最高的行。

查询:

select 
  game_type, player_id, result_date, score
from
(
  select
    game_type, player_id, result_date, score,
    dense_rank() over (partition by game_type order by score desc) as game_rank
  from 
  (
    select 
      game_type, player_id, result_date, score,
      row_number() over (partition by game_type, player_id order by score desc) as rn
    from results
    where result_date >= date '2020-01-01'
  ) top_games
  where rn = 1
) top_players
where game_rank <= 3
order by game_type, score desc;

如果玩家在多个日期在一种游戏类型中得分最高,则使用ROW_NUMBER 任意选择一个。至于玩家,也要考虑平局,决定是用RANK还是DENSE_RANK。我在查询中使用DENSE_RANK

【讨论】:

  • 谢谢,这给了我想要的结果。该表包含 5M+ 行,因此如果在较长的日期期间运行,查询似乎有点慢。我确实有一个带有 (result_date, game_type, score) 的索引,但它似乎没有任何区别?
  • 索引看起来不错,但是如果您希望玩家在每种游戏类型中获得最高分,您应该包括玩家:create index idx on results (result_date, game_type, player_id, score desc)。但是,是否使用它取决于 DBMS。日期期间越长,使用该索引的可能性就越小。
  • 好吧,我可以看到,当我运行较长的日期周期时,它没有使用索引,查询时间长达 20 秒。你说有什么我可以改变的吗?
  • 对不起,不,我不是 MySQL 专家。看起来我们对此无能为力,但谁知道呢?您可能希望将此作为一个新请求,包括执行计划。也许精通 MySQL 的人可以提供帮助。
猜你喜欢
  • 2021-07-31
  • 2018-01-16
  • 2019-10-09
  • 2012-05-26
  • 1970-01-01
  • 2011-11-23
  • 2022-01-03
  • 2017-11-22
  • 1970-01-01
相关资源
最近更新 更多