10
votes

MySQL, obtenez le rang des utilisateurs

J'ai une table mysql comme ci-dessous:

id     name     points
1      john     4635
3      tom      7364
4      bob      234
6      harry    9857


0 commentaires

3 Réponses :


18
votes
SELECT  uo.*, 
        (
        SELECT  COUNT(DISTINCT ui.points)
        FROM    users ui
        WHERE   ui.points >= uo.points
        ) AS rank
FROM    users uo
WHERE   id = @id

9 commentaires

Je l'aime. Un peu de réglage et cela correspond à mes besoins. Merci d'avoir partagé!


Problème mineure: S'il y a des liens, cela retournera le rang le plus élevé plutôt que le plus bas. Si vous voulez le plus bas, changez la condition sur > et la valeur sur comptent (*) + 1 .


@Barmar: S'il y a des liens, cela utilisera ID comme critère secondaire.


Ahh, n'a pas réalisé que vous pourriez faire une comparaison composée comme celle-là. Bien qu'il semble arbitraire qu'un joueur soit mieux classé, simplement parce qu'ils ont un identifiant supérieur. Tout le monde dans une cravate devrait avoir le même rang.


@Barmar: Pour émuler dense_rank (c'est ce dont vous parlez) il suffit de remplacer comptez (*) avec compteur (points distincts)


Cela fusionnera des liens devant vous aussi. Si les scores sont 10, 9, 9, 8, 8, les rangs doivent être de 1, 2, 2, 4, 4 (ou, plus spécifiquement, 1, 2-3, 2-3, 4-5, 4-5 ).


@Barmar: Il existe trois fonctions de fenêtre pour le classement: Row_Number (ma requête d'origine), (code> (votre commentaire précédent) et dense_rank (mon précédent commenter). Comme ils existent tous et sont utilisés, je n'utiliserais pas «devrait» sans connaître les intentions exactes de l'OP.


Je pense que la manière dont les classements dans un jeu sont généralement déclarés sont la façon dont j'ai décrit. Ils rapporteront quelque chose comme "liés pour la 4ème et la 5ème place". S'il y a une cravate pour la 1ère place, le joueur après qu'ils obtiennent la 3ème place, pas 2e.


@Quassnoi vous semblez comprendre cela beaucoup mieux que la plupart des utilisateurs, un travail fantastique!



2
votes

Solution de @Quassnoi échouera en cas de cravates. Voici la solution qui fonctionnera en cas de cravates: xxx


1 commentaires

À noter, le rang sera 0 si la première place a un score de 0. En outre, en cas de cravates, le rang est incrémenté, non ignoré par ex. 10 - 1er 9 - 2e, 9 - 2e, 6 - 3ème. De plus, la récupération des rangées devrait être dans une sous-requête, car la commande est appliquée après le classement.



0
votes
 SET @rownum := 0;
 SELECT rank, score FROM ( SELECT @rownum := @rownum +1 AS rank, `score` ,`user_id`
 FROM leaderboard 
 ORDER BY  `score` DESC , `updated_timestamp` ) as result WHERE `user_id`=$user_id
 LIMIT 1

0 commentaires