问题
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 Scores
with 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).
来源:https://stackoverflow.com/questions/27231364/mysql-get-rank-from-leaderboards