Oracle,如何从 table 中删除几乎相同的行

Oracle, how to remove almost same rows from the table

多年来,由于拼写错误,我们的数据表中添加了一些重复项。因此,例如有人拼错了名字,而不是 O'leary 写了 Oleary。我们的系统认为它是一个完全不同的名字并且不会抱怨它,但是在大多数情况下它的同一个联系人输入了两次(我没有建立这个系统)。

现在我想做的是删除所有这些重复项,但我很难构建一个查询来显示它们。我对 UTL_MATCH 进行了实验,并编写了一个查询,如果我提供名称,该查询将 return 所有相似的名称。

select first_name from customers 
where UTL_MATCH.edit_distance_similarity(first_name,'Oleary') > 60
order by first_name;

不过,我想构建一个查询,该查询可以自动 return 所有可能的重复项,而无需提供名称。谁能给我指出正确的方向?

您可以将其用于 join:

select c1.first_name, c2.first_name
from customers c1 join
     customers c2
     on UTL_MATCH.edit_distance(c1.first_name, c2.first_name) <= 3
order by c1.first_name;

备注:

  • 我更喜欢 edit_distance() 而不是 edit_distance_similarity(),因为我理解单位。
  • 连接会很慢,很慢,很慢,所以希望你没有太多行。
  • 可能会有很多假匹配,所以要小心。

像这样的东西在技术上是可行的。

select c1.first_name, c2.first_name
  from customers c1
       cross join customers c2
 where utl_match.edit_distance_similarity( c1.first_name, c2.first_name ) > 60
 order by c1.first_name

但是,它会非常慢,除非你的 customers table 恰好非常(非常)小,因为你要比较 customers [=22= 中的每一行] 与 table 中的每一行相对(并且您的编辑距离相似性截止值非常低)。为了加快速度,您可能不得不对数据做出假设或做一些其他可以作为初步过滤的事情。例如,如果您假设任何重复项都以相同的第一个字符或相同的前几个字符(忽略标点符号)开头,那么您可以大大减少需要匹配的对数,但可能会遗漏 "Kustin" 可能是 "Justin" 的拼写错误副本,其中第一个字符不同。要求 c2.customer_id > c1.customer_id 将是另一个合理的过滤器,假设您不需要复制每一对(即 "Kustin/ Justin" 行可以在没有等效的 "Justin/ Kustin" 行的情况下存在)。