it-swarm-eu.dev

Získejte hodnocení uživatele v tabulce skóre

Mám velmi jednoduchou tabulku MySQL, kde si ukládám hlavní body. Vypadá to takto:

Id     Name     Score

Zatím je vše dobré. Otázka zní: Jak zjistím, co si uživatelé řadí? Například mám uživatele Name nebo Id a chci získat jeho pořadí, kde jsou všechny řádky uspořádány sestupně pro Score.

Příklad

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

V tomto případě by byla hodnost Assem 3, protože získal 3. nejvyšší skóre.

Dotaz by měl vrátit jeden řádek, který obsahuje (pouze) požadované hodnocení.

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

dává tento seznam:

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

Získání skóre jedné osoby:

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'

Dává tento výsledek:

id name score rank
5 Assem 99 3

Budete mít jeden test, abyste získali seznam skóre, a další sken nebo pokuste se s ním udělat něco užitečného. Index ve sloupci score by pomohl výkonu na velkých tabulkách.

35
cairnz

Pokud má více záznamů stejné skóre, nemělo by být následující pořadí po sobě jdoucí. Příští pořadí by mělo být zvýšeno o počet bodů, které sdílejí stejné pořadí.

Chcete-li zobrazit skóre, jako to vyžaduje dvě proměnné pořadí

  • proměnná pořadí k zobrazení
  • proměnná pozice k výpočtu

Zde je stabilnější verze žebříčku s vazbami:

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;

Zkusme to s ukázkovými daty. První Zde jsou ukázková data:

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

Pojďme načíst ukázková data

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

Dále nechte inicializovat uživatelské proměnné:

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)

Tady je výstup dotazu:

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)

Vezměte prosím na vědomí, že více ID, které sdílejí stejné skóre, mají stejné hodnocení. Také si všimněte, že pozice není po sobě jdoucí.

Pokusit se !!!

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

Jednou z možností by bylo použití proměnných USER:

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

přijatá odpověď má potenciální problém. Pokud jsou k dispozici dvě nebo více stejných skóre, budou v hodnocení existovat mezery. V tomto upraveném příkladu:

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

Skóre 58 má 5 a žádné 4.

Pokud se chcete ujistit, že v žebříčku nejsou mezery, použijte DISTINCT v GROUP_CONCAT sestavit seznam odlišných skóre:

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

Výsledek:

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

To také funguje pro získání hodnocení jednoho uživatele:

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'

Výsledek:

id name score rank
 2  Boo   58    4
4
Mahesh Lakher

Zde je nejlepší odpověď:

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 ;

Tento dotaz vrátí:

3

3
FamerJoe

Toto řešení dává DENSE_RANK v případě vazeb:

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

Nebyla by následující práce (za předpokladu, že se váš stůl nazývá skóre)?

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