1

I am not sure if this question has been asked yet but I don't know how to word it better :)

I have a table with game results. I need to return the top 10 results (for a leaderboard) but my results has to return the highest game per player and not replicate the player (so I am looking for each players highest score and based on that the top 10 players, not say if I am 1st and 3rd on scores to show me twice).

The SQL I am using at the moment is:

 SELECT 
        `games`.`score`,
        CONCAT(`users`.`full_name`) AS `name`,
        `users`.`facebook_id`
        FROM 
        `games`,
        `users` 
        WHERE 
        `games`.`user_id`=`users`.`id` 
        AND `users`.`id` IN ('user ids goes here') 
        AND `games`.`status`=2
        ORDER BY 
        `games`.`score` DESC 
        LIMIT 10";

Can this be done with a single query or would it be best to work on the returned array and create my desired results from there?

UPDATE:

To best illustrate, say we have the following results:

Jack - 300 points
Jill - 280 points
Gareth - 250 points
Jack - 240 points (this is the same jack)
Peter - 230 points 
....

I want to return from all of the games the top 10 players based on their highest score, so not neccesarily 10 results, but I'm looking for a result which would then return the following:

Jack - 300 points
Jill - 280 points
Gareth - 250 points
Peter - 230 points 

So The 2nd Jack is removed because he is already on the list just with a higher score.

I hope this helps :)

fancyPants
  • 50,732
  • 33
  • 89
  • 96
mauzilla
  • 3,574
  • 10
  • 50
  • 86
  • I'm not understanding your question; do you have a small example of data and expected output? – Explosion Pills Sep 13 '13 at 15:19
  • Something with `GROUP BY users.id` and `MAX(games.score)` ? Depending on your database server possibly. – CD001 Sep 13 '13 at 15:27
  • ... actually - ^ that won't work as it'll **only** return the best score, not the top 10. May need a sub-query, but that effectively acts as another database query so, unless you're going to build a stored procedure, the overhead is probably less to just fetch the results from the database and sort it out in the application. – CD001 Sep 13 '13 at 15:31
  • @ExplosionPills I added some additional info to best illustrate what I'm looking for – mauzilla Sep 13 '13 at 15:33
  • possible duplicate of [Get top n records for each group of grouped results](http://stackoverflow.com/questions/12113699/get-top-n-records-for-each-group-of-grouped-results) – Marc B Sep 13 '13 at 15:48

2 Answers2

0

I think what you need is the following query:

SELECT 
    MAX(`games`.`score`),
    CONCAT(`users`.`full_name`) AS `name`,
    `users`.`facebook_id`
FROM 
    `games`
JOIN `users` 
    ON `games`.`user_id` = `users`.`id` 
WHERE `users`.`id` IN ('user ids goes here') 
    AND `games`.`status`=2
GROUP BY `name`
ORDER BY `games`.`score` DESC 
LIMIT 10";

Just using a simple MAX(games.score) would do the trick along with grouping the result together.

hjpotter92
  • 78,589
  • 36
  • 144
  • 183
0

Okay, let's do this step by step.

With this query, we get a list of games and their players, sorted by game and score. We add a rownumber which resets to 1 for each game.

SELECT 
games.game_id,
`games`.`score`,
CONCAT(`users`.`full_name`) AS `name`,
`users`.`facebook_id`,
@row_num := if(@game != games.game_id, 1, @row_num + 1) AS rownumber,
@game := games.game_id
FROM 
`games`
INNER JOIN users ON `games`.`user_id`=`users`.`id` 
, (select @row_num := 1, @game := NULL) variables
WHERE 
`users`.`id` IN ('user ids goes here') 
AND `games`.`status`=2
ORDER BY 
games.game_id, /*or something*/
`games`.`score` DESC 

Now we can get the top 10 players for each game by putting above query into this

SELECT * FROM (
<above query here>
) subquery_alias
WHERE rownumber <= 10;

Now we just have to add a GROUP BY playername and get the greatest result. So your final query is this:

SELECT name, MAX(score) FROM (
SELECT 
games.game_id,
`games`.`score`,
CONCAT(`users`.`full_name`) AS `name`,
`users`.`facebook_id`,
@row_num := if(@game != games.game_id, 1, @row_num + 1) AS rownumber,
@game := games.game_id
FROM 
`games`
INNER JOIN users ON `games`.`user_id`=`users`.`id` 
, (select @row_num := 1, @game := NULL) variables
WHERE 
`users`.`id` IN ('user ids goes here') 
AND `games`.`status`=2
ORDER BY 
games.game_id, /*or something*/
`games`.`score` DESC 
) subquery_alias
WHERE rownumber <= 10
GROUP BY `name`
fancyPants
  • 50,732
  • 33
  • 89
  • 96