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

时间:2016-10-13 15:09:50

标签: sql oracle plsql oracle11gr2

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

现在我想要做的是删除所有这些重复项,但我很难构建一个查询来显示它们。我确实尝试了UTL_MATCH并编写了一个查询,如果我提供名称,它将返回所有相似的名称。

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

但是,我想构建一个查询,该查询将自动返回所有可能的重复项,而无需提供名称。有人能指出我正确的方向吗?

2 个答案:

答案 0 :(得分:3)

您可以将其用于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(),因为我了解单位。
  • 连接将是缓慢,缓慢,缓慢的,所以希望你没有太多多行。
  • 可能会有很多假匹配,所以要小心。

答案 1 :(得分:3)

这样的东西在技术上会起作用。

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表恰好非常(非常)小,否则它会非常慢,因为你要将customers表中的每一行与表中的每一行进行比较(和您的编辑距离相似性截止值非常低。为了加快速度,你可能不得不对你的数据做出假设,或做一些可以作为初步过滤器的事情。例如,如果您假设任何重复项都以相同的第一个字符开头,或者相同的前几个字符忽略标点符号,那么您可以大大减少需要匹配的对的数量,但有可能错过“Kustin”可能的事实是“贾斯汀”的拼写复制品,其中第一个字符是不同的。要求c2.customer_id > c1.customer_id是另一个合理的过滤器,考虑假设您不需要每一对重复(即“Kustin / Justin”行可以存在而没有等效的“Justin / Kustin”行)。