I have a table called Scores
which contains columns: id
, player_id
, value1
, value2
, value3
and date
.
The table has next following content:
+------+-----------+--------+--------+--------+------------+
| id | player_id | value1 | value2 | value3 | date |
+------+-----------+--------+--------+--------+------------+
| 1 | 1 | 10 | 0 | 0 | 2012-08-02 |
+------+-----------+--------+--------+--------+------------+
| 2 | 2 | 15 | 1 | 0 | 2012-08-03 |
+------+-----------+--------+--------+--------+------------+
| 3 | 3 | 9 | 0 | 0 | 2012-08-04 |
+------+-----------+--------+--------+--------+------------+
| 4 | 1 | 11 | 0 | 0 | 2012-08-05 |
+------+-----------+--------+--------+--------+------------+
| 5 | 2 | 16 | 2 | 0 | 2012-08-06 |
+------+-----------+--------+--------+--------+------------+
| 6 | 2 | 15 | 0 | 0 | 2012-08-07 |
+------+-----------+--------+--------+--------+------------+
I am trying to get a query which returns the best highscore of each player ordered by the value in "value1, value2, value3". Value1 is the field with more importance, value2 medium importance and value3 minor importance, example:
value1 = 15 value1 = 15
value2 = 1 is greater than -> value2 = 0
value3 = 0 value3 = 1
The expected result from the query which I need is:
+------+-----------+--------+--------+--------+------------+
| id | player_id | value1 | value2 | value3 | date |
+------+-----------+--------+--------+--------+------------+
| 5 | 2 | 16 | 2 | 0 | 2012-08-06 |
+------+-----------+--------+--------+--------+------------+
| 4 | 1 | 11 | 0 | 0 | 2012-08-05 |
+------+-----------+--------+--------+--------+------------+
| 3 | 3 | 9 | 0 | 0 | 2012-08-04 |
+------+-----------+--------+--------+--------+------------+
I'm trying with MAX, DISTINCT, GROUP BY and sub-queries but I don't get the correct result. Basically it is the next query but picking the first row of each "group":
SELECT id, player_id, value1, value2, value3
FROM scores
ORDER BY value1 DESC, value2 DESC, value3 DESC
------EDIT 1-------
eggyal's answer works fine but, maybe, the performance is not too good. I need to benchmark his solution against large database to check response times.
I have had an idea (and possible solution). The solution consists adding new boolean column which says if that score is the best score of that player or not. This way I need to check if the new score is better than the best old score of that player when I'm adding new score into DB, if it is I need to mark the flag as false in the old best score and as true in the new score. This gives me a way to retrieve the best score of each player directly (simple query like SELECT ... FROM .... ORDER BY
).
------EDIT 2-------
weicap's answer is the fastest solution. I don't know why but his query is twice more faster than eggyal's query.
------EDIT 3------- I was wrong, weicap's query is more faster if the query was cached previously, if it wasn't the query takes ten or more seconds. In change, weicap's answer always takes 300-400ms against 80.000 rows.