it-swarm.asia

Dapatkan peringkat pengguna di tabel skor

Saya memiliki tabel MySQL yang sangat sederhana tempat saya menyimpan skor tinggi. Itu terlihat seperti itu:

Id     Name     Score

Sejauh ini bagus. Pertanyaannya adalah: Bagaimana cara saya mendapatkan peringkat pengguna? Sebagai contoh, saya memiliki pengguna Name atau Id dan ingin mendapatkan peringkatnya, di mana semua baris diperintahkan turun untuk Score.

Sebuah contoh

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

Dalam hal ini, peringkat Assem akan menjadi 3, karena ia mendapat skor tertinggi ke-3.

Kueri harus mengembalikan satu baris, yang berisi (hanya) Peringkat yang diperlukan.

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

berikan daftar ini:

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

Mendapatkan skor satu orang:

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'

Memberikan hasil ini:

id name score rank
5 Assem 99 3

Anda akan memiliki satu pemindaian untuk mendapatkan daftar skor, dan pemindaian lainnya atau berusaha melakukan sesuatu yang bermanfaat dengannya. Indeks pada kolom score akan membantu kinerja pada tabel besar.

35
cairnz

Ketika beberapa entri memiliki skor yang sama, peringkat berikutnya tidak boleh berturut-turut. Peringkat berikutnya harus ditambah dengan jumlah skor yang memiliki peringkat yang sama.

Untuk menampilkan skor seperti itu diperlukan dua variabel peringkat

  • variabel peringkat untuk ditampilkan
  • variabel peringkat untuk menghitung

Ini adalah versi peringkat yang lebih stabil dengan ikatan:

SET @rnk=0; SET @rank=0; SET @curscore=0;
SELECT score,ID,rank FROM
(
    SELECT AA.*,BB.ID,
    (@rnk:[email protected]+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;

Mari kita coba ini dengan data sampel. Pertama di sini adalah data sampel:

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

Mari kita memuat data sampel

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

Selanjutnya, mari inisialisasi variabel pengguna:

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)

Sekarang, ini adalah output dari query:

mysql> SELECT score,ID,rank FROM
    -> (
    ->     SELECT AA.*,BB.ID,
    ->     (@rnk:[email protected]+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)

Harap perhatikan bagaimana beberapa ID yang memiliki skor yang sama memiliki peringkat yang sama. Perhatikan juga bahwa peringkat tidak berurutan.

Cobalah !!!

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

Salah satu opsi adalah menggunakan variabel USER:

SET @i=0;
SELECT id, name, score, @i:[email protected]+1 AS rank 
 FROM ranking 
 ORDER BY score DESC;
9
Derek Downey

The jawaban yang diterima memiliki potensi masalah. Jika ada dua atau lebih skor identik, akan ada kesenjangan dalam peringkat. Dalam contoh yang dimodifikasi ini:

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

Skor 58 memiliki peringkat 5, dan tidak ada peringkat 4.

Jika Anda ingin memastikan tidak ada kesenjangan dalam peringkat, gunakan DISTINCT dalam GROUP_CONCAT untuk membuat daftar skor berbeda:

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

Hasil:

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

Ini juga berfungsi untuk mendapatkan peringkat pengguna tunggal:

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'

Hasil:

id name score rank
 2  Boo   58    4
4
Mahesh Lakher

Inilah jawaban terbaik:

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 ;

Kueri ini akan kembali:

3

3
FamerJoe

Solusi ini memberikan DENSE_RANK dalam hal ikatan:

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

Bukankah pekerjaan berikut (dengan asumsi meja Anda disebut Skor)?

SELECT COUNT(id) AS rank FROM Scores 
WHERE score <= (SELECT score FROM Scores WHERE Name = "Assem")
0
bfredo123