점수 표에서 사용자의 순위를 가져옵니다. 최고 점수를 저장하는 매우 간단한

최고 점수를 저장하는 매우 간단한 MySQL 테이블이 있습니다. 그것은 다음과 같습니다

Id     Name     Score

여태까지는 그런대로 잘됐다. 문제는 사용자 순위를 어떻게 얻습니까? 예를 들어 사용자가 Name있거나 Id순위를 얻으려고합니다 Score. 여기서 모든 행은 순서대로 내림차순으로 정렬 됩니다.

Id  Name    Score
1   Ida     100
2   Boo     58
3   Lala    88
4   Bash    102
5   Assem   99

이 경우에, Assem그는 3 번째로 높은 점수를 얻었 기 때문에 순위가 3이됩니다.

쿼리는 필요한 순위를 포함하는 하나의 행을 반환해야합니다.



답변

SELECT id, name, score, FIND_IN_SET( score, (
SELECT GROUP_CONCAT( score
ORDER BY score DESC )
FROM scores )
) AS rank
FROM scores

이 목록을 제공합니다.

id name  score rank
1  Ida   100   2
2  Boo    58   5
3  Lala   88   4
4  Bash  102   1
5  Assem  99   3

한 사람의 점수 받기 :

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'

이 결과를 제공합니다 :

id name score rank
5 Assem 99 3

당신은 점수 목록을 얻기 위해 하나의 스캔을 가지고 다른 스캔 또는 유용한 무언가를 시도합니다. score열의 인덱스는 큰 테이블에서 성능을 향상시키는 데 도움이됩니다.


답변

여러 항목이 동일한 점수를 갖는 경우 다음 순위는 연속적이어서는 안됩니다. 다음 순위는 같은 순위를 공유하는 점수의 수만큼 증가해야합니다.

그런 점수를 표시하려면 두 순위 변수가 필요합니다

  • 표시 할 순위 변수
  • 계산할 순위 변수

보다 안정적인 순위 순위는 다음과 같습니다.

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;

샘플 데이터로 이것을 시도해 봅시다. 먼저 샘플 데이터는 다음과 같습니다.

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);

샘플 데이터를로드하자

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

다음으로 사용자 변수를 초기화하십시오.

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)

다음은 쿼리 출력입니다.

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)

동일한 점수를 공유하는 여러 ID가 동일한 순위를 갖는 방법에 유의하십시오. 또한 순위는 연속적이지 않습니다.

시도 해봐 !!!


답변

SELECT
    id,
    Name,
    1+(SELECT count(*) from table_name a WHERE a.Score > b.Score) as RNK,
    Score
FROM table_name b;

답변

하나의 옵션은 USER 변수를 사용하는 것입니다.

SET @i=0;
SELECT id, name, score, @i:=@i+1 AS rank
 FROM ranking
 ORDER BY score DESC;

답변

허용 대답은 잠재적 인 문제가있다. 동일한 점수가 두 개 이상인 경우 순위에 차이가 있습니다. 이 수정 된 예에서 :

 id name  score rank
 1  Ida   100   2
 2  Boo    58   5
 3  Lala   99   3
 4  Bash  102   1
 5  Assem  99   3

58 점은 5 점이며 4 점은 없습니다.

순위에 차이가 없는지 확인하려면를 사용 DISTINCT하여 GROUP_CONCAT고유 한 점수 목록을 작성하십시오.

SELECT id, name, score, FIND_IN_SET( score, (
SELECT GROUP_CONCAT( DISTINCT score
ORDER BY score DESC ) FROM scores)
) AS rank
FROM scores

결과:

id name  score rank
1  Ida   100   2
2  Boo    58   4
3  Lala   99   3
4  Bash  102   1
5  Assem  99   3

이것은 또한 단일 사용자 순위를 얻는 데 효과적입니다.

SELECT id, name, score, FIND_IN_SET( score, (
SELECT GROUP_CONCAT(DISTINCT score
ORDER BY score DESC )
FROM scores )
) AS rank
FROM scores
WHERE name =  'Boo'

결과:

id name score rank
 2  Boo   58    4

답변

가장 좋은 답변은 다음과 같습니다.

SELECT 1 + (SELECT count( * ) FROM highscores a WHERE a.score > b.score ) AS rank FROM
highscores b WHERE Name = 'Assem' ORDER BY rank LIMIT 1 ;

이 쿼리는 다음을 반환합니다.


답변

이 솔루션은 다음 DENSE_RANK과 같은 경우에 제공합니다 .

SELECT *,
IF (@score=s.Score, @rank:=@rank, @rank:=@rank+1) rank,
@score:=s.Score score
FROM scores s,
(SELECT @score:=0, @rank:=0) r
ORDER BY points DESC