MySQL update table only with the highest values of another table
Clash Royale CLAN TAG#URR8PPP
MySQL update table only with the highest values of another table
For a game site.
All games are recorded if the player's score is greater than his old score
Table of all players (over 10,000 players)
CREATE TABLE games (
PlayerID INT UNSIGNED,
Date TIMESTAMP(12),
Score BIGINT UNSIGNED DEFAULT 0,
#...other data
);
Once a month, I do an update of the table of records best
. And after I erase all games
.
best
games
Table of best players (top 50)
CREATE TABLE best (
#...same as games, without final other data
PlayerID INT UNSIGNED,
Date TIMESTAMP(12),
Score BIGINT UNSIGNED DEFAULT 0
);
So I add the 50 best players of the table games
in to the table best
:
games
best
INSERT INTO best (PlayerID, Date, Score)
SELECT PlayerID, Date, Score FROM games ORDER BY Score DESC LIMIT 50;
And after (and this is where I have a problem) I try to keep in best
only the best 50. At this point best
contains 100 lines.
best
best
What I have to do:
PlayerID
Score
->
+----------+---------+
| PlayerID | Score |
+----------+---------+
| 25 | 20000 | New
| 25 | 25000 | Old best
| 40 | 10000 | Old best
| 57 | 80000 | New best
| 57 | 45000 | Old
| 80 | 35000 | New best
+----------+---------+
I have to retain in the end only 50 lines (the ones with "best" in my example).
I tried many things, but I have not succeeded in achieve the expected result.
I am using PHP, so if it is possible to do it simply with a intermediare storage in an array, that's fine too.
The speed is not a priority because it is an operation that is done only once a month.
@Phate01 Yes I do that for a month. But at the end of the month I clear the game table. Everything is reset to zero. I just keep track of the top 50 of all time ...
– Croises
Feb 10 '15 at 15:00
Ok so you can merge your selection with the best table using UNION
– Phate01
Feb 10 '15 at 15:02
@Phate01 And in the end replace the entire contents with the result? And erase the last lines to keep only 50. I do not know which way to turn the request with the tests better Scores and PlayerID equality.
– Croises
Feb 10 '15 at 15:09
Umm.. why not truncate best before running the insert?
– ethrbunny
Feb 10 '15 at 15:20
2 Answers
2
The following SQL returns the top 50 scores:
SELECT `PlayerId`, max(`Score`) MaxScore
FROM (
SELECT `PlayerId`, `Date`, `Score` FROM games
UNION
SELECT `PlayerId`, `Date`, `Score` FROM best
) t
GROUP BY `PlayerId`
ORDER BY `MaxScore` DESC
LIMIT 50
You can use the result to overwrite the table best
. For this you also need the corresponding Date
field, which is missing so far. The next SQL will also return a maxDate
field which corresponds to the highscore.
best
Date
maxDate
SELECT t2.`PlayerId`, max(t2.`Date`) maxDate, top.`MaxScore`
FROM
(
SELECT `PlayerId`, max(`Score`) MaxScore
FROM (
SELECT `PlayerId`, `Date`, `Score` FROM games
UNION
SELECT `PlayerId`, `Date`, `Score` FROM best
) t1
GROUP BY `PlayerId`
ORDER BY `MaxScore` DESC
LIMIT 50
) top
LEFT JOIN (
SELECT `PlayerId`, `Date`, `Score` FROM games
UNION
SELECT `PlayerId`, `Date`, `Score` FROM best
) t2 ON t2.`PlayerId` = top.`PlayerId` AND t2.`Score` = top.`MaxScore`
GROUP BY t2.`PlayerId`
ORDER BY top.`MaxScore` DESC
To transfer the new top 50 highscores into the best
table you can use a temporary table like tmp_best
. Insert the top scores into the empty table tmp_best
with (you have to insert your select query from above):
best
tmp_best
tmp_best
INSERT INTO tmp_best (`PlayerId`, `Date`, `Score`)
SELECT ...
After this the best
table can be emptied and then you can copy the rows from tmp_best
into best
.
best
tmp_best
best
Here is an alternative solution, which has simplified SQL. The difference
to the solution above is the using of a temporary table tmp_all
at the beginning for the unified data. Before using the following SQL you have to create tmp_all
, which can be a copy of the structure of games
or best
.
tmp_all
tmp_all
games
best
DELETE FROM tmp_all;
INSERT INTO tmp_all
SELECT `PlayerId`, `Date`, `Score` FROM games
UNION
SELECT `PlayerId`, `Date`, `Score` FROM best
;
DELETE FROM best;
INSERT INTO best (`PlayerId`, `Date`, `Score`)
SELECT t2.`PlayerId`, max(t2.`Date`) maxDate, top.`MaxScore`
FROM
(
SELECT `PlayerId`, max(`Score`) MaxScore
FROM tmp_all t1
GROUP BY `PlayerId`
ORDER BY `MaxScore` DESC
LIMIT 50
) top
LEFT JOIN tmp_all t2 ON t2.`PlayerId` = top.`PlayerId` AND t2.`Score` = top.`MaxScore`
GROUP BY t2.`PlayerId`
ORDER BY top.`MaxScore` DESC
;
Thank you. I do not have the ability to immediately test. May I ask how I can overwrite the table
best
in the same query.– Croises
Feb 10 '15 at 15:43
best
@Croises I would use a temporary table. After creating a temporary table with the new values you can empty the
best
table and copy the rows from the temporary table.– Henrik
Feb 10 '15 at 15:51
best
I have to test. But I think I can use a simpler solution, such as @Phate01because I have only one entry per player. I only records the highest score per player during the month. And in this case, I do not have to use
max()
.But I must get the same result simply with sorts (?)– Croises
Feb 10 '15 at 16:16
max()
@Croises As soon as you union the selects you can have two entries for one user, from the table
best
and the table games
.– Henrik
Feb 10 '15 at 16:27
best
games
Yes, that's exactly what I was thinking just now.
– Croises
Feb 10 '15 at 16:31
SELECT PlayerID, Date, Score FROM games ORDER BY Score DESC LIMIT 50
UNION
SELECT PlayerID, Date, Score FROM best
Here you'll get the best 50 players all-time. Then, as suggested by @ethrbunny, erase the best table and populate it again with the above query. You can use a TEMPORARY TABLE
UNION guarantees you that you'll get no duplicated player
Thank you. I can't erase the
best
table before if you use it in your query ?– Croises
Feb 10 '15 at 15:45
best
Since I haven't tested it, try first the selection to see if it works. Then you can simply drop it with
DROP TABLE
and then recreate it with CREATE TABLE
– Phate01
Feb 10 '15 at 15:51
DROP TABLE
CREATE TABLE
@Croises If you empty your table before using it to select your data, there will be no data any more!
– Henrik
Feb 10 '15 at 15:55
This hadn't crossed my mind at all :D
– Phate01
Feb 10 '15 at 15:56
"UNION guarantees you that you'll get no duplicated player" - this is not true.
– Henrik
Feb 10 '15 at 16:27
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Couldn't you query on the players' table to find best ones instead of creating a new table?
– Phate01
Feb 10 '15 at 14:58