代码之家  ›  专栏  ›  技术社区  ›  Andreas Linden

MySQL专家:删除所有X天以上的行,但不是最新的行

  •  8
  • Andreas Linden  · 技术社区  · 14 年前

    首先,这是创建“玩家历史记录”的查询 如果昨天没有历史记录行,或者自从过去的最新历史记录条目以来值发生了变化,那么它只能为玩家创建新的历史记录行。

    INSERT INTO `player_history` (`player_id`, `date`, `races`, `maps`, `playtime`, `points`)
    SELECT `p`.`id`, DATE_SUB(NOW(), INTERVAL 1 DAY), `p`.`races`, `p`.`maps`, `p`.`playtime`, `p`.`points`
    FROM `player` `p`
    WHERE `p`.`playtime` IS NOT NULL
    AND `p`.`playtime` > 0
    AND (
        SELECT `player_id`
        FROM `player_history`^
        WHERE `player_id` = `p`.`id`
        AND (
            `date` = DATE_SUB(NOW(), INTERVAL 1 DAY)
            OR (
                `date` < DATE_SUB(NOW(), INTERVAL 1 DAY)
                AND `races` = `p`.`races`
                AND `points` = `p`.`points`
                AND `maps` = `p`.`maps`
                AND `playtime` = `p`.`playtime`
            )
        )
        ORDER BY `date` DESC
        LIMIT 1
    ) IS NULL;
    

    现在的问题是,我还想使用单个查询清理历史记录表。这已经选择了所有超过10天的历史记录条目,但是最新的。但我不能只喜欢删除而不是选择*。

    SELECT *
    FROM `player_history` `ph`
    WHERE `date` < DATE_SUB(NOW(), INTERVAL 10 DAY)
    AND `date` != (SELECT `date`
        FROM `player_history`
        WHERE `player_id` = `ph`.`player_id`
        ORDER BY `date` DESC
        LIMIT 1);
    

    那么,tehre是一种使用单个删除查询来完成我想要的工作的方法吗?

    2 回复  |  直到 14 年前
        1
  •  9
  •   Jürgen Steinblock    14 年前

    在我看来,您的查询是正确的,但子查询中没有间隔。

    我会这样做:

    DELETE FROM player_history
    WHERE date < DATE_SUB(NOW(), INTERVAL 10 DAY)
    AND date != (
        SELECT MAX(date) FROM player_history
        WHERE date < DATE_SUB(NOW(), INTERVAL 10 DAY)
    )
    

    MySQL的错误信息是什么?

        2
  •  1
  •   Mark Byers    14 年前

    可能您不能在单个查询中执行此操作,因为 documentation 国家:

    当前,不能从表中删除并从子查询中的同一表中选择。

    作为解决方法,您可以选择必须删除到临时表中的行的ID,然后使用多表删除语句从原始表中删除记录。