MySQL Get Rank from Leaderboards

2020-05-06 12:26发布

问题:

I am implementing leaderboards in a game based on very good tutorial.

http://gamedevelopment.tutsplus.com/tutorials/how-to-code-a-self-hosted-phpsql-leaderboard-for-your-game--gamedev-11627

I am quite new to MySQL, but I got some basics. But there is a part of the code which I am totally clueless how actually works and because I don't want to implement something which doesn't make any sense to me I wanted to ask if someone could please help me understand this. It handles returning player's rank in the leaderboards:

SELECT  uo.*,
    (
    SELECT  COUNT(*)
    FROM    Scores ui
    WHERE   (ui.score, -ui.ts) >= (uo.score, -uo.ts)
    ) AS rank
FROM    Scores uo
WHERE   name = '$name';

My understanding is that first everything in the Scores table gets selected, then amount of rows gets selected, I don't understand how that selection works tho, how is the WHERE working is totaly beyond me with the timestamp. And then I am not sure how it works all together.

回答1:

When the database executes this query, first it selects from Scores, filtering by name = '$name'.

Then, for every row, it executes the subquery:

(
 SELECT  COUNT(*)
   FROM    Scores ui
  WHERE   (ui.score, -ui.ts) >= (uo.score, -uo.ts)
) AS rank

It means that, for every row of Scoreswith the searched name, it searches how many records are in Scores where (ui.score, -ui.ts) is greater or equals to the current row's values.

I hope to have helped you...



回答2:

A fact from algebra is that -A >= -B if-and-only-if A <= B.

So the expression (ui.score, -ui.ts) >= (uo.score, -uo.ts)

is just a fancy way of checking that ui.score >= ui.score AND ui.ts <= uo.ts.

The reason for including the timestamp is so that there's a "tie breaker" to uniquely define a rank.

I'm not sure if using the (A, -B) >= (A2, -B2) provides any performance advantage over just writing (A >= A2) AND (B <= B2).