问题
I know this is a popular topic, but I still haven't found quite what I'm looking for. I'd like to query one table
BOOKS_READ
id
user_id
book_id
to format a leaderboard of users who have listed the most books as having been read. When a user reads a book, a record matching the book id and the user id gets logged into the books_read table.
Is it possible to rank the results of this query, starting at 1, and with consideration of ties?
SELECT user_id, COUNT(*) AS book_count
FROM books_read
GROUP BY user_id
ORDER BY book_count DESC LIMIT 10
In the event of a tie, I would like to list an '=' sign in the results.
For example,
rank user_id book_count
=1 30 121
=1 17 121
2 101 119
=3 11 104
=3 91 104
Many thanks for any help! I don't mind using PHP to handle some of it, but I'm very interested in learning straight SQL solutions to these kinds of things :-)
回答1:
SELECT GROUP_CONCAT(user_id, book_count
FROM (
SELECT user_id, COUNT(*) AS book_count
FROM books_read
GROUP BY user_id
ORDER BY book_count DESC
) AS T1
GROUP BY book_count
ORDER BY book_count
Giving you
user_id book_count
30,17 121
101 119
11,91 104
Which you can then use PHP to parse for ties.
<?php
$rank = 1;
while ($row = mysql_fetch_assoc($result)) {
$users = explode(',', $row['user_id'];
foreach ($users as $user) {
echo 'Rank: ' . $rank . ' ' . $user . "\n;
}
$rank++;
}
?>
回答2:
What you want to do is count the number of people who have a better score than the record you're interested in, and add 1.
So, if you're the best player, zero people have a better score, so 0 + 1 = #1 ranking.
If five people have a better score, regardless of how many of them tied with each other, you're still 5 + 1 = 6.
The problem is that this is kind of an expensive query to do for every row you display. So you probably want to do it for the first row in your result set and then add one for everyone after that in your presentation layer (PHP). Be sure to take ties into consideration as you do this.
And the edge condition is that you don't know if the first row in your result set is tied with people ahead of "him". So you need to know how many people have the same score as the first person in your result set. (If you're starting at the top, this isn't a problem.)
来源:https://stackoverflow.com/questions/7072276/mysql-querying-a-leaderboard-with-ties