我有一个非常简单的 MySQL 表,用于保存高分。它看起来像这样:
Id Name Score
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好。问题是:我如何获得用户排名?例如,我有一个用户NameorId并且想要获得他的排名,其中所有行都按Score.
一个例子
Id Name Score
1 Ida 100
2 Boo 58
3 Lala 88
4 Bash 102
5 Assem 99
Run Code Online (Sandbox Code Playgroud)
在这种情况下,Assem的排名将是 3,因为他获得了第三高的分数。
查询应返回一行,其中包含(仅)所需的排名。
小智 40
SELECT id, name, score, FIND_IN_SET( score, (
SELECT GROUP_CONCAT( score
ORDER BY score DESC )
FROM scores )
) AS rank
FROM scores
Run Code Online (Sandbox Code Playgroud)
给出这个列表:
id name score rank
1 Ida 100 2
2 Boo 58 5
3 Lala 88 4
4 Bash 102 1
5 Assem 99 3
Run Code Online (Sandbox Code Playgroud)
获取单人分数:
SELECT id, name, score, FIND_IN_SET( score, (
SELECT GROUP_CONCAT( score
ORDER BY score DESC )
FROM scores )
) AS rank
FROM scores
WHERE name = 'Assem'
Run Code Online (Sandbox Code Playgroud)
给出了这个结果:
id name score rank
5 Assem 99 3
Run Code Online (Sandbox Code Playgroud)
您将进行一次扫描以获取分数列表,然后进行另一次扫描或尝试用它做一些有用的事情。score列上的索引将有助于大型表的性能。
Rol*_*DBA 33
当多个条目的分数相同时,下一个排名不应连续。下一个排名应该增加共享相同排名的分数的数量。
要显示这样的分数需要两个排名变量
这是一个更稳定的有关系的排名版本:
SET @rnk=0; SET @rank=0; SET @curscore=0;
SELECT score,ID,rank FROM
(
SELECT AA.*,BB.ID,
(@rnk:=@rnk+1) rnk,
(@rank:=IF(@curscore=score,@rank,@rnk)) rank,
(@curscore:=score) newscore
FROM
(
SELECT * FROM
(SELECT COUNT(1) scorecount,score
FROM scores GROUP BY score
) AAA
ORDER BY score DESC
) AA LEFT JOIN scores BB USING (score)) A;
Run Code Online (Sandbox Code Playgroud)
让我们用示例数据试试这个。首先这是示例数据:
use test
DROP TABLE IF EXISTS scores;
CREATE TABLE scores
(
id int not null auto_increment,
score int not null,
primary key (id),
key score (score)
);
INSERT INTO scores (score) VALUES
(50),(40),(75),(80),(55),
(40),(30),(80),(70),(45),
(40),(30),(65),(70),(45),
(55),(45),(83),(85),(60);
Run Code Online (Sandbox Code Playgroud)
让我们加载示例数据
mysql> DROP TABLE IF EXISTS scores;
Query OK, 0 rows affected (0.15 sec)
mysql> CREATE TABLE scores
-> (
-> id int not null auto_increment,
-> score int not null,
-> primary key (id),
-> key score (score)
-> );
Query OK, 0 rows affected (0.16 sec)
mysql> INSERT INTO scores (score) VALUES
-> (50),(40),(75),(80),(55),
-> (40),(30),(80),(70),(45),
-> (40),(30),(65),(70),(45),
-> (55),(45),(83),(85),(60);
Query OK, 20 rows affected (0.04 sec)
Records: 20 Duplicates: 0 Warnings: 0
Run Code Online (Sandbox Code Playgroud)
接下来,让我们初始化用户变量:
mysql> SET @rnk=0; SET @rank=0; SET @curscore=0;
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
现在,这是查询的输出:
mysql> SELECT score,ID,rank FROM
-> (
-> SELECT AA.*,BB.ID,
-> (@rnk:=@rnk+1) rnk,
-> (@rank:=IF(@curscore=score,@rank,@rnk)) rank,
-> (@curscore:=score) newscore
-> FROM
-> (
-> SELECT * FROM
-> (SELECT COUNT(1) scorecount,score
-> FROM scores GROUP BY score
-> ) AAA
-> ORDER BY score DESC
-> ) AA LEFT JOIN scores BB USING (score)) A;
+-------+------+------+
| score | ID | rank |
+-------+------+------+
| 85 | 19 | 1 |
| 83 | 18 | 2 |
| 80 | 4 | 3 |
| 80 | 8 | 3 |
| 75 | 3 | 5 |
| 70 | 9 | 6 |
| 70 | 14 | 6 |
| 65 | 13 | 8 |
| 60 | 20 | 9 |
| 55 | 5 | 10 |
| 55 | 16 | 10 |
| 50 | 1 | 12 |
| 45 | 10 | 13 |
| 45 | 15 | 13 |
| 45 | 17 | 13 |
| 40 | 2 | 16 |
| 40 | 6 | 16 |
| 40 | 11 | 16 |
| 30 | 7 | 19 |
| 30 | 12 | 19 |
+-------+------+------+
20 rows in set (0.18 sec)
Run Code Online (Sandbox Code Playgroud)
请注意共享相同分数的多个 ID 如何具有相同的排名。还要注意 rank 不是连续的。
试一试 !!!
a1e*_*x07 15
SELECT
id,
Name,
1+(SELECT count(*) from table_name a WHERE a.Score > b.Score) as RNK,
Score
FROM table_name b;
Run Code Online (Sandbox Code Playgroud)
一种选择是使用 USER 变量:
SET @i=0;
SELECT id, name, score, @i:=@i+1 AS rank
FROM ranking
ORDER BY score DESC;
Run Code Online (Sandbox Code Playgroud)