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

Posted

技术标签:

【中文标题】使用 Soundex、Jaro Winkler 和编辑距离 (UTL_MATCH) 匹配 Oracle 重复列值【英文标题】:Matching Oracle duplicate column values using Soundex, Jaro Winkler and Edit Distance (UTL_MATCH) 【发布时间】:2011-11-22 15:38:39 【问题描述】:

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

我可以使用的表格列是:

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 算法提供了更好的匹配水平。

有没有人实施了一种可靠的方法来匹配此类数据,而不是重新发明***?

需要解决的数据质量问题:

    邮政编码虽然是强制性的,但并不总是完全输入。 地址数据质量相对较差,地址输入格式不固定(例如,有些可能将 line1 设为“Flat 1”,而有些可能将 line1 设为“Flat1, 22 Acacia Ave”)。 名字列可以包含一个名字首字母、一个完整的名字,有时也可以包含多个名字。

例如我正在考虑:

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

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

Oracle 10g R2 企业版。

欢迎任何有用的建议。

【问题讨论】:

当您在标题中说“重复的列值”时,实际上是指“相似”或“几乎相同”。 是的,我想“重复”在逻辑上是不正确的,他们是同一个人,但数据不完全匹配。 【参考方案1】:

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

唉,没有这样的事情。您最多可以期望的是一个具有合理怀疑因素的系统。

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%。压倒性的缺点是分数是相对的,因此您无法索引它们。这种比较会在大量的情况下杀死你。

这意味着:

    您需要多种策略。没有一种算法可以解决您的问题。 数据清理很有用。比较 MARX 与 MRX 和 M4RX 的得分:从名称中去除数字可以提高命中率。 您无法即时为大量姓名评分。如果可以,请使用标记化和预评分。如果您没有大量流失,请使用缓存。如果您负担得起,请使用分区。 使用 Oracle Text(或类似的)构建昵称和变体的词库。 Oracle 11g 为 Oracle Text 引入了特定的名称搜索功能。 Find out more. 建立一个用于评分的规范名称表并将实际数据记录链接到该表。 使用其他数据值,尤其是可索引的数据值,如出生日期,来预过滤大量姓名或增加对提议匹配的信心。 请注意,其他数据值也有其自身的问题:有人出生于 2011 年 1 月 11 日 11 个月还是 80 岁? 请记住,名称很棘手,尤其是当您必须考虑已罗马化的名称时:Moammar Khadaffi(在罗马字母表中)有四百多种不同的拼写方式 - 甚至 Google 也无法就哪个变体是最规范。

根据我的经验,连接标记(名字、姓氏)是喜忧参半。它解决了某些问题(例如道路名称是否出现在地址行 1 或地址行 2)但会导致其他问题:考虑评分 GRAHAM OLIVER vs OLIVER GRAHAM 与评分 OLIVER vs OLIVER、GRAHAM vs GRAHAM、OLIVER vs GRAHAM 和 GRAHAM vs OLIVER .

无论您做什么,最终都会出现误报和未命中的情况。没有算法可以防止拼写错误(尽管 Jaro Winkler 在 MARX 与 AMRX 方面做得很好)。

【讨论】:

这就是我要找的。其中一些我已经实现了,但其他一些部分是金粉。非常感谢。首先,我将对 Metaphone 算法进行一些研究。我已经以基本方式使用了模糊分数,并且有一些很好的方法可以找到置信度阈值,因此您提供的其他信息将与此非常吻合。很好的答案! @APC 当我们需要比较字符串 b/w 2 个不同的表时,我们如何做到这一点,没有公共键并且查找表的记录比其他表多?

以上是关于使用 Soundex、Jaro Winkler 和编辑距离 (UTL_MATCH) 匹配 Oracle 重复列值的主要内容,如果未能解决你的问题,请参考以下文章

带有 Jaro-Winkler 相似距离算法的 EF Core

Jaro-Winkler Distance

Jaro-Winkler distance

考试答案匹配算法

Pyspark:如何处理 python 用户定义函数中的空值

亲和传播偏好参数