Bart van Heukelom
Bart van Heukelom

Reputation: 44084

SQL Group By: Get values of 'max' record

I have a scores table:

id
user
score
date

Now, I can easily select a top 10 highscore with

SELECT user, score, date FROM scores ORDER BY score DESC

However, I'd like to include only one score per user, namely his highest. I would begin with something like

SELECT user, MAX(score) AS score FROM scores GROUP BY user ORDER BY score DESC

However, now I've lost the date that highest score was recorded. How do I get it?

Upvotes: 0

Views: 482

Answers (4)

Incidently
Incidently

Reputation: 4349

In fact, you don't need a GROUP BY at all.

Here's the query:

SELECT scores.id, scores.user, scores.score, scores.date
FROM scores
WHERE NOT EXISTS (
  SELECT * 
  FROM scores AS _scores
  WHERE _scores.user = scores.user
  AND (
    _scores.score > scores.score
    OR
    _scores.score = scores.score AND _scores.id < scores.id) 
)

and SQL Fiddle to see it working.

Note that this query properly handles the case when a user had his max score several times (it returns the record for the first max score).

Upvotes: 1

Taryn
Taryn

Reputation: 247660

You can JOIN on the table again:

SELECT s1.user, max(s1.dt), s2.mxscore as score
FROM scores s1
inner join 
(
    select user, max(score) mxscore
    from scores
    GROUP BY user 
) s2
    on s1.user = s2.user
    and s1.score = s2.mxscore
GROUP BY s1.username, s2.mxscore
ORDER BY score DESC

See SQL Fiddle with Demo

Upvotes: 1

Zane Bien
Zane Bien

Reputation: 23125

SELECT   a.*
FROM     scores a
JOIN     (
         SELECT   MAX(a.id) AS id
         FROM     scores a
         JOIN     (
                  SELECT   user, MAX(score) AS score
                  FROM     scores
                  GROUP BY user
                  ) b ON a.user  = b.user
                     AND a.score = b.score
         GROUP BY a.user, 
                  a.score
         ) b ON a.id = b.id
ORDER BY a.score DESC

This will account for cases where you have more than one of the same highest score per user. In that case, it will just take the maximum id.

Upvotes: 0

Barranka
Barranka

Reputation: 21047

You will need to relate your result with your original table:

select a.user, a.maxScore, b.maxDate
from (
    select user, max(score) as maxScore 
    from scores group by user ) as a
inner join (
    select user, score, max(date) as maxDate 
    from scores group by user, score) as b on a.user = b.user and a.maxScore=b.score
order by
    a.maxScore desc

This query will return the maximum score for each user, and the last date when this maximum score was scored (redundant, but true)

Upvotes: 0

Related Questions