Domanda

While making a game the MySQL call to get the top 10 is as follows:

SELECT username, score FROM userinfo ORDER BY score DESC LIMIT 10

This seems to work decently enough, but when paired with a call to get a individual player's rank the numbers may be different if the player has a tied score with other players. The call to get the players rank is as follows:

SELECT (SELECT COUNT(*) FROM userinfo ui WHERE (ui.score, ui.username) >= (uo.score, uo.username)) AS rank FROM userinfo uo WHERE username='boddie';

Example results from first call:

+------------+-------+
| username   | score |
+------------+-------+
| admin      |  4878 |
| test3      |  3456 |
| char       |   785 |
| test2      |   456 |
| test1      |   253 |
| test4      |    78 |
| test7      |     0 |
| boddie     |     0 |
| Lz         |     0 |
| char1      |     0 |
+------------+-------+

Example results from second call

+------+
| rank |
+------+
|   10 |
+------+

As can be seen, the first call ranks the player at number 8 on the list, but the second call puts him at number 10. What changes or what can I do to make these calls give matching results?

Thank you in advance for any help!

È stato utile?

Soluzione

You need in the first query to :

ORDER BY 
   score DESC,
   username DESC

This way it will reach at rank 10... this is due to the username comparison in the second query :

(ui.score, ui.username) >= (uo.score, uo.username)

Altri suggerimenti

I would change your Order by to include username, so that you always get the same order. So it would look like:

... ORDER BY score DESC, username ASC ...

Another way of doing it:-

SELECT UsersRank
FROM 
(
    SELECT userinfo.score, userinfo.username, @Rank:=@Rank+1 AS UsersRank
    FROM userinfo 
    CROSS JOIN (SELECT (@Rank:=0)) Sub1
    ORDER BY userinfo.score DESC, userinfo.username
) Sub2
WHERE username = 'boddie'
SELECT
    uo.username,
    (SELECT COUNT(*)+1 FROM userinfo ui WHERE ui.score>uo.score) AS rank
FROM userinfo uo
WHERE uo.username='boddie'

Or if you need to get username, score and ranks:

SELECT
    uo.username,
    uo.score,
    (@row := @row + 1) AS rank
FROM userinfo uo
JOIN (SELECT @row := 0) r
ORDER BY uo.score DESC, uo.username ASC

You could add

HAVING uo.username = 'boddie'

to get only one user

Try this.

SELECT (COUNT(*)+1) AS rank
FROM   userinfo ui
WHERE  ui.score > (SELECT score
                   FROM   userinfo
                   WHERE  username='boddie');
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top