MySQL: Querying a leaderboard with ties

*爱你&永不变心* 提交于 2019-12-22 09:15:05

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!