최고 점수를 저장하는 매우 간단한 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