获取用户在评分表中的排名

Mic*_*ael 36 mysql rank

我有一个非常简单的 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列上的索引将有助于大型表的性能。

  • 相关的`(SELECT GROUP_CONCAT(score) FROM TheWholeTable)` 不是最好的方法。并且创建的行的大小可能有问题。 (3认同)
  • 对于较大的表,单人分数查询非常慢。确定单人分数的排名(有平局的差距)的更好的查询是:`SELECT 1 + COUNT(*) ASrank FROM Scores WHERE Score > (SELECT分数来自分数 WHERE name='Assem')`。其中“just”计算得分高于当前条目的条目数。(如果您添加“DISTINCT”,您将获得无间隙的排名..) (3认同)
  • 如果有关系,这将失败。 (2认同)

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)


Der*_*ney 9

一种选择是使用 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)