我是sql的新手,我从未在mysql中使用变量或条件,但是从其他编程语言中知道。几天后,我试图找到一种方法来对用户评分进行排名。我阅读了很多文章,还有关于stackoverflow的问题,最后我发现了一个几乎像我想要的解决方案。
SELECT
score_users.uid,
score_users.score,
@prev := @curr,
@curr := score,
@rank := IF(@prev = @curr, @rank, @rank +1) AS rank
FROM
score_users,
(SELECT @curr := null, @prev := null, @rank := 0) tmp_tbl
WHERE
score_users.matchday = 1
ORDER BY
score_users.score DESC
但我的问题是平局得分。我不想获得连续的排名,如下:
+------------+------+--------+
| uid | name | rank | score |
+------------+------+--------+
| 4 | Jon | 1 | 20 |
| 1 | Jane | 2 | 19 |
| 2 | Fred | 2 | 19 |
| 9 | July | 3 | 18 |
| 7 | Mary | 4 | 17 |
| 3 | Toni | 5 | 12 |
| 5 | Steve | 5 | 12 |
| 6 | Peter | 6 | 11 |
| 8 | Nina | 7 | 10 |
+------------+------+--------+
我想得到这样的结果:
+------------+------+--------+
| uid | name | rank | score |
+------------+------+--------+
| 4 | Jon | 1 | 20 |
| 1 | Jane | 2 | 19 |
| 2 | Fred | 2 | 19 |
| 9 | July | 4 | 18 |
| 7 | Mary | 5 | 17 |
| 3 | Toni | 6 | 12 |
| 5 | Steve | 6 | 12 |
| 6 | Peter | 8 | 11 |
| 8 | Nina | 9 | 10 |
+------------+------+--------+
我想我必须创建一个新的临时表,有些条件,但我无法找到解决方案并变得绝望! 此外,我必须密切关注表现,也许有更好的方法来获得我的分数排名?我会非常感谢提示或一些代码片段。
答案 0 :(得分:4)
您可以使用另一个变量来计算相同的排名,而不是将@rank
递增1,而是将@rank
递增计数器值,如下所示:
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
答案 1 :(得分:0)
添加另一个始终递增的排名字段。如果值匹配,则使用现有等级(不递增),否则使用总是递增的等级。
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
答案 2 :(得分:0)
在关系上,您可能希望跳过并将当前行号用作下一个不匹配的得分值行作为下一个等级。 以下应该可以帮到你
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