Mysql 仅删除连续的重复行
我从API中收集数据来构建历史记录。最初,我每五分钟保存一次所有值。后来,我更改了程序,只保存已更改的数据 现在,我想清理我的旧数据,并删除同一帐户和id中计数与上一条记录没有更改的所有值 我试着用一个小组来解决这个问题,通过帐户、id和计数。然而,使用这种方法,它将删除非连续的重复项,即,如果一条记录在一段时间后再次具有相同的值,它将属于同一组Mysql 仅删除连续的重复行,mysql,sql,sql-delete,Mysql,Sql,Sql Delete,我从API中收集数据来构建历史记录。最初,我每五分钟保存一次所有值。后来,我更改了程序,只保存已更改的数据 现在,我想清理我的旧数据,并删除同一帐户和id中计数与上一条记录没有更改的所有值 我试着用一个小组来解决这个问题,通过帐户、id和计数。然而,使用这种方法,它将删除非连续的重复项,即,如果一条记录在一段时间后再次具有相同的值,它将属于同一组 我还考虑编写一个小脚本,在该脚本中,如果account、id和count与上一条记录相同,我将迭代所有数据并删除当前行,但我很好奇,如果使用一条SQL
我还考虑编写一个小脚本,在该脚本中,如果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语句的进度。是的,关于性能,你是对的。如果这是一个一次性执行语句,那么这应该不是什么大问题。使用变量来模拟窗口函数可能会导致更有效的解决方案。第三行是另一个帐户,因此它是按升序排列的,不是吗?