MySQL Rank with ties

孤街浪徒 提交于 2019-11-29 07:01:44

You can use another variable to count the same ranks so instead of incrementing @rank by 1, you increment @rank by the counter value, like this:

SELECT
  score_users.uid,
  score_users.score,
  @prev := @curr,
  @curr := score,
  @rank := IF(@prev = @curr, @rank, @rank + @i) AS rank,
  IF(@prev <> score, @i:=1, @i:=@i+1) AS counter
FROM
  score_users,
  (SELECT @curr := null, @prev := null, @rank := 0, @i := 0) tmp_tbl
WHERE
  score_users.matchday = 1
ORDER BY
  score_users.score DESC

Add another rank field which is always incremented. If the value matches you use your existing rank (not incremented), if not you use your always incremented rank.

SELECT
  score_users.uid,
  score_users.score,
  @prev := @curr,
  @curr := score,
  @rank1 := @rank1 + 1,
  @rank := IF(@prev = @curr, @rank, @rank1) AS rank 
FROM
  score_users,
  (SELECT @curr := null, @prev := null, @rank := 0, @rank1 := 0) tmp_tbl
WHERE
  score_users.matchday = 1
ORDER BY
  score_users.score DESC

On ties, you may want to skip and use current row num to next unmatched score value row as next rank. Following should help you

SELECT
    score_users.uid
  , @curr_score := score_users.score as score,
  , case when @prev_score = @curr_score then @rank := @rank 
         else @rank := ( @curr_row + 1 ) -- <- this is what you require
     end as rank
  , @curr_row := ( @curr_row + 1 ) as curr_row
  , @prev_score := @curr_score
FROM
  score_users,
  ( SELECT @curr_score := 0, @prev_score := 0
         , @curr_row := 0,   @rank := 0 ) initializer
WHERE
  score_users.matchday = 1
ORDER BY
  score_users.score DESC
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!