I have a table in which users store scores and other information about said score (for example notes on score, or time taken etc). I want a mysql query that finds each users personal best score and it’s associated notes and time etc.
What I have tried to use is something like this:
SELECT *, MAX(score) FROM table GROUP BY (user)
The problem with this is that whilst you can extra the users personal best from that query [MAX(score)], the returned notes and times etc are not associated with the maximum score, but a different score (specifically the one contained in *). Is there a way I can write a query that selects what I want? Or will I have to do it manually in PhP?
You can join with a sub query, as in the following example:
The above query can be explained as follows. It starts with:
… This by itself will obviously list all the contents of the table. The goal is to keep only the rows that represent a maximum score of a particular user. Therefore if we had the data below:
…We would have wanted to keep just the “note c” and “note e” rows.
To find the rows that we want to keep, we can simply use:
Note that we cannot get the notes attribute from the above query, because as you had already noticed, you would not get the expected results for fields not aggregated with an aggregate function, like
MAX()or not part of theGROUP BYclause. For further reading on this topic, you may want to check:Now we only need to keep the rows from the first query that match the second query. We can do this with an
INNER JOIN:The sub query is given the name
sub_t. It is the set of all the users with the personal best score. TheONclause of theJOINapplies the restriction to the relevant fields. Remember that we only want to keep rows that are part of this subquery.