有没有更快的方法从一个表中删除重复项?

Posted

技术标签:

【中文标题】有没有更快的方法从一个表中删除重复项?【英文标题】:is there a faster way to remove dublicates from one table? 【发布时间】:2019-03-29 11:45:34 【问题描述】:

我有一个 184k 记录的表,并且有一些重复的键 concat(tradedate,stock_short)。我的方法如下:

Delete from levermannwithoutdub where recnum not in
(Select max(recnum) from leverman groub by concat(tradedate,stock_short));

levermanwithoutdubleverman 两个表开头都是一样的。

但该操作现在需要 15000 秒并且仍在工作。

有没有更快的方法来删除重复的最大(recnum)应该保留的重复?

我试图理解下面的尝试:

但我仍然有大约 2500 个重复记录,同一记录最多 38 个副本。

如何在所有 2528 个重复项上运行它?

法西特: 我做了以下事情: 创建一个空的同一个表,索引对 (tradedate,stock_short) 是唯一的。 以 recnum 降序导出旧表。 通过 Workbench 导入并忽略错误。

只花了大约 5 分钟。 我知道这不是复杂的方法,但它比 通过 SET 的 recnums 删除它。

此外:我发现:Tutorial 从我做这个的地方:

    DELETE t1 FROM levermann t1
    INNER JOIN
    lev_mitdup_Lnotnull t2 
    WHERE
     t1.recnum < t2.recnum AND concat(t1.tradedate,t1.stock_short) = 
     concat(t2.tradedate,t2.stock_short);

【问题讨论】:

recnum、tradedate、stock_short 是否有索引? @J.R.此时没有。但我会这样做,如果它更快的话。 我猜您将从recnum 上的非唯一索引和(tradedate, stock_short) 上的非唯一索引中受益匪浅,并且还可以在没有concat 的情况下使用您的查询,即delete from levermannwithoutdub where recnum not in (Select max(recnum) from leverman groub by tradedate,stock_short) ; 【参考方案1】:

确保您在表leverman 列上有一个索引(tradedate、stock_short) 避免在 where 和 group by 中使用 concat,并使用子查询来减少重复行的搜索

Delete twd
from levermannwithoutdub  twd
inner join (
  SELECT max(recnum)  max_recnum
  FROM leverman l
  INNER JOIN (
    SELECT  tradedate,stock_short
    FROM leverman 
    GROUP BY tradedate,stock_short 
    HAVING COUNT(*) > 1 
  ) t ON  t.tradedate = l.tradedate 
        AND  t.stock_short = l.stock_short  
) r on  r.max_recnum = twd.recnum 

如果你有更多的值不仅是重复的,而且是三倍的,或者更多,你需要再次运行删除查询

您可以检查您使用的价值如何

    SELECT  tradedate,stock_short, count(*) dup
    FROM leverman 
    GROUP BY tradedate,stock_short 
    HAVING COUNT(*) > 1 
    ORDER BY dup desc

每个交易日都有很多重复的实例,stock_short 您也可以尝试删除所有匹配 tradedate、stock_short 并且是 that max_recnum

的行
Delete  twd
from levermannwithoutdub  twd
inner join (
  SELECT max(l.recnum)  max_recnum, t.tradedate, t.stock_short
  FROM leverman l
  INNER JOIN (
    SELECT  tradedate,stock_short
    FROM leverman 
    GROUP BY tradedate,stock_short 
    HAVING COUNT(*) > 1 
  ) t ON  t.tradedate = l.tradedate 
        AND  t.stock_short = l.stock_short  
) r on  r.max_recnum <>   twd.recnum 
      AND  r.tradedate = twd.tradedate 
        AND  r.stock_short = twd .stock_short  

【讨论】:

非常感谢!但我有相同的记录 35 - 25 份。我只能在运行一段时间后安装唯一索引。所以这是一个更快的问题,让你的脚本运行 35 次,或者我的脚本只运行一次。这是一个有趣的问题。 答案已更新,建议避免 35 次重复执行 .. 请查看我对您的解决方案的更新问题。非常感谢您的帮助。 @sciasEdge 你的语法有误:Delete &lt;table&gt; from .. 查看我的更新。 @WalterSchrabmair 回答更新删除 twd from

以上是关于有没有更快的方法从一个表中删除重复项?的主要内容,如果未能解决你的问题,请参考以下文章

从具有 NULL 列的大表中删除重复项,这也需要考虑

从 Netezza 表中删除重复项

了解从链表中删除重复项的复杂性

从 MySQL 中的大表中删除重复项的最快过程是啥

从文件或表中删除重复项

如何删除 Access 表中的重复项(不使用查询)?