MySQL - 根据列子集重复删除行

时间:2018-03-12 10:16:18

标签: mysql sql duplicates subset sql-delete

我有一个包含大约500万行和150列的表。但是,有几个类似的行,如果他们为3列共享相同的值,我想考虑重复:IDOrderName

但是,我不只是想随机删除重复项,我希望我认为重复的行是具有较小计数值的行(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分钟)然后从服务器退出,所以我不确定这是否正确我只需要运行更长时间或如果代码本质上是错误的,并且有更快的方法。

3 个答案:

答案 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 1LIMIT 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
相关问题