Mr. Messy
Mr. Messy

Reputation: 308

MySQL - How to select rows with max value of a field

I have a table of users with their scores for each level of a game:

id | user_id | level | score
1  | David   | 1     | 20
2  | John    | 1     | 40
3  | John    | 2     | 30
4  | Mark    | 1     | 60
5  | David   | 2     | 10
6  | David   | 3     | 80
7  | Mark    | 2     | 20
8  | John    | 3     | 70
9  | David   | 4     | 50
10 | John    | 4     | 30

What is the SQL query needed to get for each level, who has the highest score?

The result should be:

id | user_id | level | score
4  | Mark    | 1     | 60
3  | John    | 2     | 30
6  | David   | 3     | 80
9  | David   | 4     | 50

Thank you

Upvotes: 9

Views: 17701

Answers (3)

Paul Spiegel
Paul Spiegel

Reputation: 31832

If you only want the user, who reached the highest score first (no ties per level):

select *
from users u1
where id = (
    select id
    from users u2
    where u2.level = u1.level
    order by score desc, id asc
    limit 1
)

You should have indexes (id) and (level, score, id)

Upvotes: 0

Mak
Mak

Reputation: 154

order by score desc in sub query, then select max(score) group by level.

select id, user_id , level , max(score) as score
from
(select * from scores order by score desc)A 
group by level  

Upvotes: 1

Gordon Linoff
Gordon Linoff

Reputation: 1270823

If you want to get ties, then you can do something like this:

select s.*
from scores s
where s.score = (select max(s2.score) from scores s2 where s2.level = s.level);

You could get one row per level by aggregating this:

select s.level, s.score, group_concat(s.user_id)
from scores s
where s.score = (select max(s2.score) from scores s2 where s2.level = s.level)
group by s.level, s.score;

This combines the users (if there is more than one) into a single field.

Upvotes: 14

Related Questions