我有一个包含大约500万行和150列的表。但是,有几个类似的行,如果他们为3列共享相同的值,我想考虑重复:ID
,Order
和Name
。
但是,我不只是想随机删除重复项,我希望我认为重复的行是具有较小计数值的行(Count
是另一列)或者如果它们有相同的计数,然后将其置于具有最早日期列的位置(Date
是另一列)。
我尝试过以下代码:
DELETE t1 FROM uploaddata_copy t1
JOIN uploaddata_copy t2
ON t2.Name = t1.Name
AND t2.ID = t1.ID
AND t2.Order = t1.Order
AND t2.Count < t1.Count
AND t2.Date < t1.Date
然而(这可能是由于我的电脑)它似乎无限期地运行(约25分钟)然后从服务器退出,所以我不确定这是否正确我只需要运行更长时间或如果代码本质上是错误的,并且有更快的方法。
答案 0 :(得分:1)
更准确的查询是:
DELETE t1
FROM uploaddata_copy t1 JOIN
uploaddata_copy t2
ON t2.Name = t1.Name AND
t2.ID = t1.ID AND
t2.Order = t1.Order AND
(t2.Count < t1.Count OR
t2.Count = t1.Count AND t2.Date < t1.Date
);
但是,修复逻辑不会(在这种情况下)提高性能。首先,您需要uploaddata_copy(Name, Id, Order, Count, Date)
上的索引。这允许&#34;查找&#34;在原始数据和仅索引之间。
第二,从小做起。添加LIMIT 1
或LIMIT 10
以查看仅删除几行所需的时间。删除行是一个复杂的过程,因为它会影响表,索引和事务日志 - 更不用说表上的任何触发器了。
如果要删除大量行,您可能会发现重新创建表的速度更快,但这在很大程度上取决于要删除的相对行数。
答案 1 :(得分:1)
为何加入?您希望在存在时删除行 a&#34;更好&#34;记录。所以使用EXISTS
子句:
delete from dup using uploaddata_copy as dup
where exists
(
select *
from uploaddata_copy better
where better.name = dup.name
and better.id = dup.id
and better.order = dup.order
and (better.count > dup.count or (better.count = dup.count and better.date > dup.date))
);
(请检查我的比较。这就是我理解这一点:更好的记录名称+ id +订单有更多的计数或相同的计数和更高的日期。你认为更糟糕的记录是你想要删除的不需要的重复。)
即使在uploaddata_copy(id, name, order)
上,您的uploaddata_copy(id, name, order, count, date)
索引也至少或更好,因此此删除语句效果不错。
答案 2 :(得分:0)
请试试这个:
DELETE t1 FROM uploaddata_copy t1
JOIN uploaddata_copy t2
ON t2.Name = t1.Name
AND t2.ID = t1.ID
AND t2.Order = t1.Order
AND t2.Count < t1.Count
AND t2.Date < t1.Date
AND t2.primary_key != t1.primary_key