سؤال

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 :)

هل كانت مفيدة؟

المحلول

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`

نصائح أخرى

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.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top