使用Soundex,Jaro Winkler和编辑距离(UTL_MATCH)匹配Oracle重复列值

时间:2011-11-22 15:38:40

标签: oracle plsql oracle10g data-quality

我正在尝试找到一种可靠的方法来匹配数据库中的重复人员记录。数据有一些严重的数据质量问题,我也试图解决这个问题,但在我批准之前,我仍然坚持使用我得到的数据。

我可以使用的表格列是:

SURNAME       VARCHAR2(43)
FORENAME      VARCHAR2(38)
BIRTH_DATE    DATE
ADDRESS_LINE1 VARCHAR2(60)
ADDRESS_LINE2 VARCHAR2(60)
ADDRESS_LINE3 VARCHAR2(60)
ADDRESS_LINE4 VARCHAR2(60)
ADDRESS_LINE5 VARCHAR2(60)
POSTCODE      VARCHAR2(15)

SOUNDEX函数对于此用途相对有限,但UTL_MATCH包似乎使用Jaro Winker算法提供更好的匹配级别。

有没有人采用可靠的方法来匹配这类数据,而不是重新发明轮子?

要应对的数据质量问题:

  1. 邮政编码虽然是强制性的,但并不总是完全输入。
  2. 地址数据质量相对较差,地址没有固定格式输入(即某些地方可能将line1设为“Flat 1”,而有些地址可能将line1设为“Flat1,22 Acacia Ave”)。
  3. forename列可以包含一个首字母,一个完整的名字,有时还包含一个以上的名字。
  4. 例如我在考虑:

    连接所有地址字段并将Jaro Winkler算法应用于完整地址,并结合对连接在一起的全名的类似测试。

    出生日期可以直接比较匹配,但由于大量数据只是匹配,这是不够的。

    Oracle 10g R2企业版。

    欢迎任何有用的建议。

1 个答案:

答案 0 :(得分:6)

  

“我正在努力寻找一种匹配重复人的可靠方法   数据库中的记录。“

唉,没有这样的事情。你最希望的是一个具有合理怀疑元素的系统。

SQL> select n1
       , n2
       , soundex(n1) as sdx_n1
       , soundex(n2) as sdx_n2
       , utl_match.edit_distance_similarity(n1, n2) as ed
       , utl_match.jaro_winkler_similarity(n1, n2) as jw   
from t94
order by n1, n2
/


  2    3    4    5    6    7    8    9  
N1                   N2                   SDX_ SDX_         ED         JW
-------------------- -------------------- ---- ---- ---------- ----------
MARK                 MARKIE               M620 M620         67         93
MARK                 MARKS                M620 M620         80         96
MARK                 MARKUS               M620 M622         67         93
MARKY                MARKIE               M620 M620         67         89
MARSK                MARKS                M620 M620         60         95
MARX                 AMRX                 M620 A562         50         91
MARX                 M4RX                 M620 M620         75         85
MARX                 MARKS                M620 M620         60         84
MARX                 MARSK                M620 M620         60         84
MARX                 MAX                  M620 M200         75         93
MARX                 MRX                  M620 M620         75         92

11 rows selected.

SQL> SQL> SQL> 

SOUNDEX的一大优势在于它标记了字符串。这意味着它为您提供了可以编入索引的 :当涉及到大量数据时,这非常有价值。另一方面,它是旧的和粗糙的。有更新的算法,如Metaphone和Double Metaphone。您应该能够通过Google找到它们的PL / SQL实现。

得分的优势在于它们允许一定程度的模糊性;所以你可以找到所有行where name_score >= 90%。令人沮丧的缺点是分数是相对的,所以你不能索引它们。这种比较会让你大量消耗。

这意味着:

  1. 您需要各种策略。没有一种算法可以解决您的问题。
  2. 数据清理很有用。比较MARX与MRX和M4RX的得分:从名称中删除数字可提高命中率。
  3. 您无法动态获取大量名称。如果可以,请使用标记和预评分。如果您没有大量的流失,请使用缓存。如果您负担得起,请使用分区。
  4. 使用Oracle Text(或类似文件)构建昵称和变体的词库。
  5. Oracle 11g为Oracle Text引入了特定的名称搜索功能。 Find out more.
  6. 为评分建立一个规范名称表,并将实际数据记录链接到该表。
  7. 使用其他数据值,尤其是像出生日期这样的可索引数据值来预过滤大量名称或增加对拟议匹配的信心。
  8. 请注意,其他数据值有其自身的问题:11月31日至11月11日或八十岁出生的人是谁?
  9. 请记住,名字很棘手,特别是当你必须考虑已被罗马化的名字时:有超过四百种不同的拼写方法Moammar Khadaffi(罗马字母表) - 甚至谷歌都不同意哪种变体是最规范的。
  10. 根据我的经验,连接令牌(名字,姓氏)是一种喜忧参半的祝福。它解决了某些问题(例如道路名称是否出现在地址第1行或地址第2行),但会导致其他问题:考虑得分GRAHAM OLIVER vs OLIVER GRAHAM对阵得分OLIVER vs OLIVER,GRAHAM vs GRAHAM,OLIVER vs GRAHAM和GRAHAM vs OLIVER 。

    无论你做什么,你仍然会得到误报和错过命中。没有算法可以证明打字错误(尽管Jaro Winkler在MARX和AMRX方面做得相当不错)。