问题
I have a table (called users) I need rank of users based on their score but I want rank on the bases of users max score.
+-----------+------------+
| User_id | Score |
+-----------+------------+
| 1 | 12258 |
| 1 | 112 |
| 2 | 9678 |
| 5 | 9678 |
| 3 | 689206 |
| 3 | 1868 |
Expect result
+-----------+------------+---------+
| User_id | Score | Rank |
+-----------+------------+---------+
| 3 | 689206 | 1 |
| 1 | 12258 | 2 |
| 2 | 9678 | 3 |
| 5 | 9678 | 3 |
回答1:
You are looking for DENSE_RANK
, But it supports mysql version higher than 8.0
- use correlated-subquery to get
max
value by eachUser_id
- use two variables one to store
rank
another to store previous value to make theDENSE_RANK
number.
look like this.
CREATE TABLE T(
User_id int,
Score int
);
insert into t values (1,12258);
insert into t values (1,112);
insert into t values (2,9678);
insert into t values (5,9678);
insert into t values (3,689206);
insert into t values (3,1868);
Query 1:
SELECT User_id,Score,Rank
FROM (
SELECT User_id,
Score,
@rank :=IF(@previous = t1.score, @rank, @rank + 1) Rank,
@previous := t1.Score
FROM T t1 CROSS JOIN (SELECT @Rank := 0,@previous := 0) r
WHERE t1.Score =
(
SELECT MAX(Score)
FROM T tt
WHERE t1.User_id = tt.User_id
)
ORDER BY Score desc
) t1
Results:
| User_id | Score | Rank |
|---------|--------|------|
| 3 | 689206 | 1 |
| 1 | 12258 | 2 |
| 2 | 9678 | 3 |
| 5 | 9678 | 3 |
回答2:
Another trick in MySql 5.7 to calculate a DENSE_RANK (like in MySql 8) is to use a CASE WHEN with the variable assignments in it.
SELECT User_id, MaxScore AS Score,
CASE
WHEN MaxScore = @prevScore THEN @rnk
WHEN @prevScore := MaxScore THEN @rnk := @rnk+1
ELSE @rnk := @rnk+1
END AS Rank
FROM
(
SELECT User_id, MAX(Score) AS MaxScore
FROM YourTable
GROUP BY User_id
ORDER BY MaxScore DESC, User_id
) AS q
CROSS JOIN (SELECT @rnk := 0, @prevScore := null) AS vars
You can test it here on rextester.
来源:https://stackoverflow.com/questions/53020515/calculate-rank-of-the-users-based-on-their-max-score-using-mysql