对于游戏网站。
如果玩家的分数高于他的旧分数,则记录所有游戏
所有玩家的表(超过10,000名玩家)
CREATE TABLE games (
PlayerID INT UNSIGNED,
Date TIMESTAMP(12),
Score BIGINT UNSIGNED DEFAULT 0,
#...other data
);
每月一次,我会对记录表best
进行更新。擦除所有games
后。
最佳球员表(前50名)
CREATE TABLE best (
#...same as games, without final other data
PlayerID INT UNSIGNED,
Date TIMESTAMP(12),
Score BIGINT UNSIGNED DEFAULT 0
);
所以我将表games
中的50位最佳玩家添加到表best
中:
INSERT INTO best (PlayerID, Date, Score)
SELECT PlayerID, Date, Score FROM games ORDER BY Score DESC LIMIT 50;
之后(这就是我遇到问题的地方)我试着保留best
只有最好的50个。此时best
包含100行。
我必须做什么:
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
+----------+---------+
我最终只能保留50行(在我的例子中“最好”的行) 我尝试了很多东西,但是我没有成功实现预期的结果。
我正在使用PHP,所以如果可以通过数组中的中间存储来实现它,那也没关系。 速度不是优先级,因为它是一个每月只进行一次的操作。
答案 0 :(得分:1)
以下SQL返回前50个分数:
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
您可以使用结果覆盖表格best
。为此,您还需要相应的Date
字段,这是迄今为止缺少的字段。下一个SQL也将返回一个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
要将新的前50个高分转移到best
表,您可以使用tmp_best
之类的临时表。将最高分数插入空表tmp_best
中(您必须从上面插入您的选择查询):
INSERT INTO tmp_best (`PlayerId`, `Date`, `Score`)
SELECT ...
在此之后,best
表可以清空,然后您可以将tmp_best
中的行复制到best
。
这是一个替代解决方案,它简化了SQL。区别
上面的解决方案是在统一数据的开头使用临时表tmp_all
。在使用以下SQL之前,您必须创建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
;
答案 1 :(得分:0)
SELECT PlayerID, Date, Score FROM games ORDER BY Score DESC LIMIT 50
UNION
SELECT PlayerID, Date, Score FROM best
在这里,你将获得有史以来最好的50名玩家。然后,根据@ethrbunny的建议,删除最佳表并使用上述查询再次填充它。您可以使用TEMPORARY TABLE
UNION保证您不会获得重复播放器