重复数据删除表的最佳方法是什么?

fro*_*die 31 sql algorithm performance duplicates

我已经看到了几个解决方案,但我想知道最好和最有效的方法是去掉一张桌子.您可以使用代码(SQL等)来说明您的观点,但我只是在寻找基本算法.我假设在SO上已经有一个关于这个的问题了,但我找不到一个,所以如果它已经存在,那就给我一个抬头.

(只是为了澄清 - 我指的是在具有增量自动PK的表中删除重复项,并且除了PK字段之外的所有行中都有一些重复的行.)

Han*_*Gay 13

SELECT DISTINCT <insert all columns but the PK here> FROM foo.使用该查询创建临时表(语法因RDBMS而异,但通常有一个SELECT … INTOCREATE TABLE AS模式可用),然后吹掉旧表并将临时表中的数据泵回到其中.


小智 11

使用解析函数row_number:

WITH CTE (col1, col2, dupcnt)
AS
(
SELECT col1, col2,
ROW_NUMBER() OVER (PARTITION BY col1, col2 ORDER BY col1) AS dupcnt
FROM Youtable
)
DELETE
FROM CTE
WHERE dupcnt > 1
GO                                                                 
Run Code Online (Sandbox Code Playgroud)

  • @Kev您可以从CTE中删除,只要修改只会更改单个基表,这应该是这里的情况. (2认同)

HLG*_*GEM 8

重复数据删除很少很简单.这是因为要进行重复数据删除的记录通常会有一些字段略有不同.因此,选择要保留的记录可能会有问题.此外,重复通常是人员记录,并且很难确定两个约翰史密斯是两个人还是一个人是重复的.因此,花费大量时间(整个项目的50%或更多)来定义构成dup的内容以及如何处理差异和子记录.

你怎么知道哪个是正确的价值?进一步的重复数据删除要求您处理所有不是孤立的子记录.当您发现通过更改子记录中的id突然违反其中一个唯一索引或约束时会发生什么 - 这最终会发生,您的进程需要处理它.如果您愚蠢地选择仅通过应用程序应用所有约束,您可能甚至不知道违反了约束.当您有10,000条记录要进行重复数据删除时,您不会通过该应用程序一次重复删除一条记录.如果约束不在数据库中,那么在重复数据删除时保持数据完整性的运气很大.

更复杂的是,重复并不总是与名称或地址完全匹配.例如,名为Joan Martin的销售代表可能是销售代表Joan Martin-Jones的副本,特别是如果他们有相同的地址和电子邮件.或者你可以在名字中加入约翰或约翰尼.或者相同的街道地址,除了一个记录abbreveiated ST.一个拼写出街道.在SQL Server中,您可以使用SSIS和模糊分组来识别近匹配.这些通常是最常见的重复,因为不完全匹配的事实是它们首先被放入重复的原因.

对于某些类型的重复数据删除,您可能需要一个用户界面,以便执行重复数据删除的人可以选择用于特定字段的两个值中的哪一个.如果被重复数据删除的人有两个或更多角色,则尤其如此.可能是特定角色的数据通常比另一个角色的数据更好.或者可能只有用户才能确定哪个是正确的值,或者他们可能需要联系人们以确定他们是真正的重复还是仅仅是两个具有相同名称的人.


DSh*_*ook 6

如果您可以将重复条件归为一条语句,并且您的表具有一个ID标识列以确保唯一性,这就是我使用的方法:

delete t
from tablename t
inner join  
(
    select date_time, min(id) as min_id
    from tablename
    group by date_time
    having count(*) > 1
) t2 on t.date_time = t2.date_time
where t.id > t2.min_id
Run Code Online (Sandbox Code Playgroud)

在此示例中,date_time是分组条件,如果您有多个列,请确保将所有列都加入。

  • 为什么不只是:`从 pk_id 不在的表中删除(从 COL1 表组中选择 min(pk_id))` (2认同)

Dro*_*Hit 6

在此添加实际代码以供将来参考

因此,有3个步骤,因此有3个SQL语句:

步骤1:将非重复项(唯一元组)移动到临时表中

CREATE TABLE new_table as
SELECT * FROM old_table WHERE 1 GROUP BY [column to remove duplicates by];
Run Code Online (Sandbox Code Playgroud)

第2步:删除旧表(或重命名)我们不再需要包含所有重复条目的表,所以放弃它!

DROP TABLE old_table;
Run Code Online (Sandbox Code Playgroud)

第3步:将new_table重命名为old_table的名称

RENAME TABLE new_table TO old_table;
Run Code Online (Sandbox Code Playgroud)

当然,不要忘记修复您的错误代码以停止插入重复项!

  • `myTable.randomColumn 不在 GROUP BY 子句中`:( 看起来我无法在不为所有列提供聚合函数的情况下按单个列进行分组。 (2认同)

Fru*_*ner 0

您可以为每一行生成一个散列(不包括 PK),将其存储在一个新列中(或者如果您无法添加新列,您可以将表移动到临时暂存区域吗?),然后查找所有其他具有相同哈希值的行。当然,您必须能够确保哈希函数不会为不同的行生成相同的代码。

如果两行重复,删除哪一行有关系吗?其他数据是否可能依赖于两个副本?如果是这样,您将需要执行以下几个步骤:

  • 寻找受骗者
  • 选择其中一项作为dupeA消除
  • 查找依赖于的所有数据dupeA
  • 更改该数据以引用dupeB
  • 删除dupeA

这可能很简单也可能很复杂,具体取决于您现有的数据模型。

整个场景听起来像是一个维护和重新设计项目。如果是这样,祝你好运!