Home > database >  Mysql row_number rank based on value
Mysql row_number rank based on value

Time:02-21

I'm trying to find out someones ranking based on value in db. But I can't figure out row_number() here.

Base query, to which I want to add ranks:

select player_id,value from player_storage where `key` = 40001 order by value desc;
 ----------- ------- 
| player_id | value |
 ----------- ------- 
|        10 |   333 |
|        11 |    31 |
|        15 |    12 |
|         9 |     3 |
|         1 |     0 |
|         8 |     0 |
|        12 |     0 |
|        13 |     0 |
|        14 |     0 |
 ----------- ------- 

Lets say I'm player_id = 11, and I want to know what place in ranking I have.

Tried several solutions, like row_number() over (partition by value), but calculated rank is always wrong. Examples:

select player_id,value,row_number() over (partition by value order by value desc) as rank from player_storage where `key` = 40001 order by rank;
 ----------- ------- ------ 
| player_id | value | rank |
 ----------- ------- ------ 
|         1 |     0 |    1 |
|         9 |     3 |    1 |
|        10 |   333 |    1 |
|        11 |    31 |    1 |
|        15 |    12 |    1 |
|         8 |     0 |    2 |
|        12 |     0 |    3 |
|        13 |     0 |    4 |
|        14 |     0 |    5 |
 ----------- ------- ------ 

Or...

set @rank = 0 ; select rank,player_id,value from (select player_id,value,(@rank:=@rank 1) as rank from player_storage, (select @rank := 0) r where `key` = 40001 order by value desc) t order by rank;
Query OK, 0 rows affected (0.000 sec)

 ------ ----------- ------- 
| rank | player_id | value |
 ------ ----------- ------- 
|    1 |         1 |     0 |
|    2 |         8 |     0 |
|    3 |         9 |     3 |
|    4 |        10 |   333 |
|    5 |        11 |    31 |
|    6 |        12 |     0 |
|    7 |        13 |     0 |
|    8 |        14 |     0 |
|    9 |        15 |    12 |
 ------ ----------- ------- 

CodePudding user response:

Rank window function seems the obvious answer, btw partition by is optional

create table t
(player_id int, value int);
insert into t values
(        10 ,   333 ),
(        11 ,    31 ),
(        15 ,    12 ),
(         9 ,     3 ),
(         1 ,     0 ),
(         8 ,     0 ),
(        12 ,     0 ),
(        13 ,     0 ),
(        14 ,     0 );

select *,
        rank() over (order by value desc)
from t

 ----------- ------- ----------------------------------- 
| player_id | value | rank() over (order by value desc) |
 ----------- ------- ----------------------------------- 
|        10 |   333 |                                 1 |
|        11 |    31 |                                 2 |
|        15 |    12 |                                 3 |
|         9 |     3 |                                 4 |
|        13 |     0 |                                 5 |
|        14 |     0 |                                 5 |
|         1 |     0 |                                 5 |
|         8 |     0 |                                 5 |
|        12 |     0 |                                 5 |
 ----------- ------- ----------------------------------- 
9 rows in set (0.001 sec)

and if you only want for 11 put code in cte

with cte as
(select *,
        rank() over (order by value desc) rnk
from t
)
select player_id, rnk
from cte 
where player_id = 11;
  • Related