MySQL仅使用另一个表的最高值更新表
用于游戏网站。MySQL仅使用另一个表的最高值更新表,mysql,sql,Mysql,Sql,用于游戏网站。 如果玩家的分数大于其旧分数,则记录所有游戏 所有玩家列表(超过10000名玩家) 我每月更新一次记录表best。在我清除所有游戏之后 最佳球员名单(前50名) 因此,我将表格游戏中的50名最佳玩家添加到表格最佳: INSERT INTO best (PlayerID, Date, Score) SELECT PlayerID, Date, Score FROM games ORDER BY Score DESC LIMIT 50; 之后(这就是我的问题所在),我试着保持最
如果玩家的分数大于其旧分数,则记录所有游戏 所有玩家列表(超过10000名玩家) 我每月更新一次记录表
best
。在我清除所有游戏之后
最佳球员名单(前50名)
因此,我将表格游戏中的50名最佳玩家添加到表格最佳:
INSERT INTO best (PlayerID, Date, Score)
SELECT PlayerID, Date, Score FROM games ORDER BY Score DESC LIMIT 50;
之后(这就是我的问题所在),我试着保持最好的状态,只保持最好的50。此时best
包含100行
我必须做的事情:
- 不要多次存储同一播放器
PlayerID
- 删除该玩家最差的
分数
- 最后,只剩下前50名
->
最后,我只能保留50行(在我的示例中,那些带有“best”的行)。
我尝试了很多事情,但没有达到预期的效果
我使用的是PHP,所以如果可以简单地用数组中的中间存储来实现,也可以。
速度不是优先级,因为它是一个每月只执行一次的操作。以下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\u best
的临时表。将最高分插入空表tmp\u best
with(您必须从上面插入select查询):
在此之后,可以清空best
表,然后可以将行从tmp\u best
复制到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
;
这里有一个替代解决方案,它简化了SQL。区别
上面的解决方案是在统一数据的开头使用临时表tmp_all
。在使用以下SQL之前,您必须创建tmp\u all
,它可以是游戏
或最佳
结构的副本
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
;
在这里,你将有史以来最好的50名球员。然后,按照@ethrbunny的建议,删除最佳表并使用上述查询再次填充它。你可以使用
工会保证你不会得到重复的球员难道你不能查询球员表以找到最好的球员,而不是创建一个新的表吗?@Phate01是的,我这样做了一个月。但在月底,我清理了游戏桌。一切都重置为零。我只是一直跟踪前50名……好吧,这样你就可以使用@Phate01将你的选择与最佳表格合并,最后用结果替换整个内容?删除最后一行,只保留50行。我不知道该用哪种方式来处理考试成绩更好和玩家身份平等的问题。。为什么不在运行insert之前截断best?谢谢。我没有立即测试的能力。请问如何在同一查询中覆盖表best
。@croise我会使用临时表。使用新值创建临时表后,您可以清空best
表,并从临时表复制行。我必须进行测试。但我认为我可以使用一个更简单的解决方案,比如@phate01,因为我每个玩家只有一个条目。我只记录了每个球员当月的最高分数。在这种情况下,我不必使用max()
。但我必须简单地使用排序(?)@Croises获得相同的结果。只要您合并选择,您就可以为一个用户提供两个条目,分别来自表best
和表games
。是的,这正是我刚才所想的。谢谢。如果在查询中使用best
表,我以前无法删除该表?因为我没有测试它,请先尝试选择以查看它是否有效。然后,您可以使用drop TABLE
简单地删除它,然后使用CREATE TABLE
@croies重新创建它。如果在使用表选择数据之前清空表,将不再有数据!“工会保证你不会得到重复的球员”-这不是真的。是的,这是我的怀疑。我想知道测试的数据是什么。因为只有PlayerID可以是相同的。在这种情况下,永远不会有两条相同的线。
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
INSERT INTO tmp_best (`PlayerId`, `Date`, `Score`)
SELECT ...
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
;
SELECT PlayerID, Date, Score FROM games ORDER BY Score DESC LIMIT 50
UNION
SELECT PlayerID, Date, Score FROM best