Mysql 仅删除连续的重复行

Mysql 仅删除连续的重复行,mysql,sql,sql-delete,Mysql,Sql,Sql Delete,我从API中收集数据来构建历史记录。最初,我每五分钟保存一次所有值。后来,我更改了程序,只保存已更改的数据 现在,我想清理我的旧数据,并删除同一帐户和id中计数与上一条记录没有更改的所有值 我试着用一个小组来解决这个问题,通过帐户、id和计数。然而,使用这种方法,它将删除非连续的重复项,即,如果一条记录在一段时间后再次具有相同的值,它将属于同一组 我还考虑编写一个小脚本,在该脚本中,如果account、id和count与上一条记录相同,我将迭代所有数据并删除当前行,但我很好奇,如果使用一条SQL

我从API中收集数据来构建历史记录。最初,我每五分钟保存一次所有值。后来,我更改了程序,只保存已更改的数据

现在,我想清理我的旧数据,并删除同一帐户和id中计数与上一条记录没有更改的所有值

我试着用一个小组来解决这个问题,通过帐户、id和计数。然而,使用这种方法,它将删除非连续的重复项,即,如果一条记录在一段时间后再次具有相同的值,它将属于同一组


我还考虑编写一个小脚本,在该脚本中,如果account、id和count与上一条记录相同,我将迭代所有数据并删除当前行,但我很好奇,如果使用一条SQL语句,是否可以删除当前行?

您可以使用以下未经测试的代码删除除第一行之外的所有数据:

delete from history h1 
where exists (select h2 
              from history 
              where
                h1.account = h2.account and
                h1.id = h2.id and
                h1.count = h2.count and
                h1.time < h2.time
             )

您可以使用以下查询:

DELETE history 
FROM history 
INNER JOIN (SELECT MIN(time) AS minTime, account, id, count
            FROM history
            GROUP BY account, id, count) AS h
ON history.account = h.account AND history.id = h.id AND history.count = h.count
WHERE history.time > h.minTime
SELECT pk
FROM history AS h1
WHERE account = (SELECT account 
                 FROM history AS h2
                 WHERE h1.account = h2.account AND
                       h1.id = h2.id AND                       
                       h2.time < h1.time
                 ORDER BY time DESC 
                 LIMIT 1)
      AND
      id = (SELECT id 
            FROM history AS h2
            WHERE h1.account = h2.account AND
                  h1.id = h2.id AND                  
                  h2.time < h1.time
            ORDER BY time DESC 
            LIMIT 1)
      AND
      count = (SELECT count
               FROM history AS h2
               WHERE h1.account = h2.account AND
                     h1.id = h2.id AND                     
                     h2.time < h1.time
               ORDER BY time DESC 
               LIMIT 1)
编辑:

编辑完成后,我认为OP time字段的样本数据中仍然存在一些错误,应该按顺序排列

使用表中存在PK的附加假设,可以使用以下查询:

DELETE history 
FROM history 
INNER JOIN (SELECT MIN(time) AS minTime, account, id, count
            FROM history
            GROUP BY account, id, count) AS h
ON history.account = h.account AND history.id = h.id AND history.count = h.count
WHERE history.time > h.minTime
SELECT pk
FROM history AS h1
WHERE account = (SELECT account 
                 FROM history AS h2
                 WHERE h1.account = h2.account AND
                       h1.id = h2.id AND                       
                       h2.time < h1.time
                 ORDER BY time DESC 
                 LIMIT 1)
      AND
      id = (SELECT id 
            FROM history AS h2
            WHERE h1.account = h2.account AND
                  h1.id = h2.id AND                  
                  h2.time < h1.time
            ORDER BY time DESC 
            LIMIT 1)
      AND
      count = (SELECT count
               FROM history AS h2
               WHERE h1.account = h2.account AND
                     h1.id = h2.id AND                     
                     h2.time < h1.time
               ORDER BY time DESC 
               LIMIT 1)
编辑2:

使用变量查找已删除的pk值可能会导致查询速度大大加快:

SELECT pk
FROM (
  SELECT pk, account, id, count, time,
         @rn := IF (account = @acc AND id = @id AND count = @count,
                    @rn + 1, 1) AS rn,
         @acc := account,
         @id := id,
         @count := count
  FROM history
  CROSS JOIN (SELECT @rn = 0, @acc = 0, @id = 0, @count = 0) AS vars
  ORDER BY account, id, time, count ) AS t
WHERE t.rn > 1

我认为是h1.time*>*h2.time,因为OP希望保留较旧的记录,除非我遗漏了什么,否则这只会删除重复的记录,不管它们是否连续。连续的部分使这个问题变得棘手,不同于之前的十几个堆栈溢出问题。演示很棒。但是帐号2 id19684有个问题,它是805,然后上升到810,又回到805。这些都是有效的更改。但是只有接下来的两个805应该被删除,而不是第一个,而是810之后的806。我只是看到我在问题中标记了太多的一行要删除。编辑它。抱歉…@dasKeks我已经编辑了我的答案,现在应该可以了。我添加了一个pk,一般来说似乎可以。但是在一个700.000行的表中,每行有三个子选择的语句可能没有那么快。我希望人们能看到单个sql语句的进度。是的,关于性能,你是对的。如果这是一个一次性执行语句,那么这应该不是什么大问题。使用变量来模拟窗口函数可能会导致更有效的解决方案。第三行是另一个帐户,因此它是按升序排列的,不是吗?