Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MySQL仅使用另一个表的最高值更新表_Mysql_Sql - Fatal编程技术网

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