I have two tables, the first is players
x
---------------------------------------------
| player_id | player_score | player_game_id |
---------------------------------------------
| 1 | 274 | 1 |
---------------------------------------------
| 2 | 281 | 1 |
---------------------------------------------
| 3 | 156 | 2 |
---------------------------------------------
| 4 | 199 | 2 |
---------------------------------------------
| 5 | 120 | 2 |
---------------------------------------------
And another table for games
-----------------------
| game_id | game_name |
-----------------------
| 1 | gameone |
-----------------------
| 2 | gametwo |
-----------------------
I would like to have this result
----------------------------------------------------
| player_id | player_score | player_rank | game_id |
----------------------------------------------------
| 2 | 281 | 1 | 1 |
----------------------------------------------------
| 1 | 274 | 2 | 1 |
----------------------------------------------------
| 4 | 199 | 1 | 2 |
----------------------------------------------------
| 3 | 156 | 2 | 2 |
----------------------------------------------------
| 5 | 120 | 3 | 2 |
----------------------------------------------------
Have anyone idea how to achieve this in mysql? Thank you very much
Advertisement
Answer
You want rank()
or row_number()
:
select p.*,
rank() over (partition by player_game_id order by player_score desc) as rank
from players
order by player_game_id, player_score desc;
If two players have the same score, then rank()
gives them the same ranking. row_number()
will arbitrarily assign them adjacent rankings.
The above works on MySQL 8+. In earlier versions you have two options — subqueries and variables. Here is an example using a correlated subquery:
select p.*,
(select 1 + count(*)
from players p2
where p2.player_game_id = p.player_game_id and
p2.player_score > p.player_score
) as ranking
from players
order by player_game_id, player_score desc;
This is not as efficient as rank()
. But with an index on players(player_game_id, player_score)
and not too many players per game, then this should have reasonable performance.