查询清理旧表或创建新表

时间:2014-04-15 16:22:00

标签: php mysql

我有一个players表,其中包含某些玩家信息,以及一张jumps表,其中包含有关特定"跳转"的统计信息。任何玩家可能已经在记录到数据库的游戏中执行过。 jumps表还包括相应的"玩家ID"这也可以在players表中找到。

表结构如下(仅显示重要列):

players

id | name | ip | authid | lastseen

jumps

pid | type | distance | wpn

"跳转"由typedistancewpn记录。每当 distance type达到更大的wpn时,就会更新一行,这意味着每{{1}有不同的条目每个typewpn个不同的条目。

问题


该插件用于保存过去由pid而不是ip设置的信息,这导致两个表中的多余条目,其中不同的authid对应于ip { {1}} / id

目标


  1. pid表开始,我想查找并删除不包含该特定players的最大authid值的每个lastseen的所有行。最后,每authid只应该有一行。
  2. 现在是困难的部分:我不能简单地先执行删除查询来完成 1 。我可能需要最后执行该任务,因为我需要知道authid / id才能更新pid表中保留唯一jumps的所有行来自 1 。不过,等等!还有更多!还记得以前id而不是ip创建的条目吗?现在可能已经创造了#34;重叠"行,因为每authid可能有多个id / pid个值。这些现在需要删除。
  3. 困惑了吗?让我举一个例子:

    实施例


    在这里,我执行了一个简单的连接来匹配两个表中的相应行,并提供了一个示例:

    authid

    这导致以下内容我已经重新排序/格式化,以提高可读性:

    SELECT * FROM uq_jumps INNER JOIN uq_players ON uq_jumps.pid = uq_players.id WHERE authid="STEAM_X:X:XXX" AND type="bj"

    更新和插入行的插件会考虑" knife"相当于" usp"所以最后应该保留的上述条目是:

    675 | bj | 205251568 | awp
    675 | name1 | 0.0.0.0 | STEAM_X:X:XXX | 1395562981
    
    2457 | bj | 244130768 | knife
    2457 | name2 | 11.11.11.11 | STEAM_X:X:XXX | 1384822930
    
    2566 | bj | 246756784 | usp
    2566 | name3 | 10.10.10.10| STEAM_X:X:XXX | 1381841664
    
    2693 | bj | 242543040 | knife
    2693 | name3 | 9.9.9.9 | STEAM_X:X:XXX | 1381934217
    
    3483 | bj | 235620544 | usp
    3483 | name3 | 8.8.8.8 | STEAM_X:X:XXX | 1382803345
    
    3701 | bj | 243075456 | usp
    3701 | name2 | 7.7.7.7 | STEAM_X:X:XXX | 1384996069
    
    3764 | bj | 244422656 | usp
    3764 | name3 | 6.6.6.6 | STEAM_X:X:XXX | 1383253511
    
    4070 | bj | 243392880 | knife
    4070 | name3 | 5.5.5.5 | STEAM_X:X:XXX | 1383550208
    
    4179 | bj | 240038976 | knife
    4179 | name2 | 4.4.4.4 | STEAM_X:X:XXX | 1383642095
    
    4260 | bj | 243244656 | usp
    4260 | name2 | 3.3.3.3 | STEAM_X:X:XXX | 1383821359
    
    5369 | bj | 242361200 | knife
    5369 | name2 | 2.2.2.2 | STEAM_X:X:XXX | 1384629584
    
    5905 | bj | 245641984 | usp
    5905 | name2 | 1.1.1.1 | STEAM_X:X:XXX | 1385424952
    
    675 | bj | 245942608 | usp
    675 | name1 | 0.0.0.0 | STEAM_X:X:XXX | 1395562981
    
    675 | bj | 212841424 | m249
    675 | name1 | 0.0.0.0 | STEAM_X:X:XXX | 1395562981
    

    我在这里完全不知道如何生成一个新的唯一条目表或选择/删除应该正确删除或保留的条目。我最初的想法是从使用上面发布的连接语句开始。

    现在我可以通过多个查询轻松完成此操作并在PHP脚本中迭代结果数组等,但有人告诉我, 2 可以在一个查询中完成(当然这人还没有证明他们的观点。)

    任何建议,想法,甚至起点都会有所帮助。

1 个答案:

答案 0 :(得分:1)

首先将玩家表格结构复制到临时表中,让我们说一下new_players

CREATE TABLE new_players SELECT * FROM players WHERE 1=2;

现在在新创建的表中插入所需的authid和lastseen字段

INSERT INTO new_players 
SELECT authid, MAX(lastseen) AS lastseen FROM players GROUP BY authid;

填写剩下的字段

UPDATE new_players np JOIN players p 
  ON np.authid=p.authid AND np.lastseen=p.lastseen 
SET np.id   = p.id,
    np.name = p.name,
    np.ip   = p.ip
;

使用正确的跳转重新映射pid(根据new_players中的选定记录)

UPDATE jumps j LEFT JOIN new_players np ON j.pid = np.id SET
j.pid = (SELECT np2.id FROM players p JOIN new_players np2 
           ON p.authid=np2.authid AND p.lastseen=np2.lastseen 
         WHERE p.id=j.pid LIMIT 1
        )
WHERE np.id IS NULL;

现在您可以安全地清除不需要的记录

DELETE p.* FROM players p LEFT JOIN new_players np ON p.id=np.id 
WHERE np.id IS NULL;

最后清除跳转表

DELETE j.* FROM jumps LEFT JOIN (
  SELECT pid, type, wpn, MAX(distance) AS distance FROM jumps GROUP BY pid, type, wpn
) j2 ON j.pid=j2.pid AND j.type=j2.type AND j.wpn=j2.wpn AND j.distance=j2.distance
WHERE j2.pid IS NULL;

注意:因为我无法测试代码所以不确定语法的有效性。但我希望你能得到主要的想法 注意:始终备份以测试新内容