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

2023-12-10

我正在尝试找到一种可靠的方法来匹配数据库中的重复人员记录。这些数据存在一些严重的数据质量问题,我也在尝试修复这些问题,但在我获得批准之前,我只能使用现有的数据。

我可用的表列有:

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)

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

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

需要应对的数据质量问题:

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

例如我正在考虑:

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

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

Oracle 10g R2 企业版。

欢迎任何有用的建议。


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

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

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 引入了特定的名称搜索功能。了解更多。
  6. 构建用于评分的规范名称表,并将实际数据记录链接到该表。
  7. 使用其他数据值,尤其是可索引的数据值(例如出生日期)来预先过滤大量姓名或增加对建议匹配的置信度。
  8. 请注意,其他数据值也有其自身的问题:出生于 2011 年 1 月 31 日的人是十一个月还是八十岁?
  9. 请记住,名字很棘手,尤其是当您必须考虑已罗马化的名字时:Moammar Khadaffi(罗马字母表)有四百多种不同的拼写方式 - 甚至谷歌也无法就哪种变体最规范达成一致。

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

无论您做什么,您仍然会出现误报和错过命中的情况。没有算法可以防止拼写错误(尽管 Jaro Winkler 在 MARX 与 AMRX 方面做得相当不错)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • PL/SQL 过程:如何返回 select 语句?

    我想创建一个存储过程 on ORACLE数据库服务器我的问题是 我不知道如何返回 select 语句 这是程序中应包含的逻辑 输入参数 过滤器1 int 过滤器2 字符串 with cte as select val1 val2 stdde
  • 如何插入包含“&”的字符串

    如何编写包含 字符的插入语句 例如 如果我想将 J J Construction 插入数据库的列中 我不确定这是否有什么不同 但我正在使用 Oracle 9i 我总是忘记这一点 然后又回到它 我认为最好的答案是迄今为止提供的答复的组合 首先
  • 查询以查找平均加权价格

    我在 Oracle 中有一个表 每个给定部分包含多行 每行都有一个与其关联的数量和价格 还有一个给定零件的行集相加的总数量 以下是数据示例 我需要的是获得该零件的平均加权价格 例如 如果数量为 100 的零件的价格为 1 数量为 50 的零
  • Oracle 数据库 11g 中的访问控制列表 (ACL) 拒绝网络访问

    最近我们从 Oracle 10g 切换到 11g 现在我发现我的邮件功能不起作用 我现在收到错误 ORA 24247 network access denied by access control list ACL 因此 我进行了一些谷歌搜
  • 如何动态创建表数据类型的变量?

    在以下查询中 select string 可以返回具有任何可能数据类型的任意数量的列和行 Execute immediate select string into v table variable 例如 select string 可以是
  • 从 Oracle 获取包方法和参数

    我正在寻找 Oracle 查询来获取 Oracle 包 过程的所有参数 我知道有一个视图或表可以提供此功能 但我似乎不记得它是什么 注意 我并不是要从 user objects 获取包列表 而是要获取包 中每个过程的数据类型和参数名称 Th
  • 匹配可能存在或可能不存在的组

    我的正则表达式需要解析一个如下所示的地址 BLOOKKOKATU 20 A 773 00810 HELSINKI SUOMI 1 2 3 4 第一组 第二组和第三组将始终存在于地址中 第 4 组可能不存在 我编写了一个正则表达式来帮助我获得
  • 跨数据库管理系统检查字符串是否为数字的方法

    好的 我有这个字段 code varchar 255 它包含我们导出例程中使用的一些值 例如 DB84 DB34 3567 3568 我需要仅选择自动生成的 全数字 字段 WHERE is numeric table code is num
  • ORA-12154: TNS: 无法解析指定的连接标识符

    当我安装服务器版本和现有的 Oracle 10g 客户端版本时 问题就开始了 背景 安装了 Oracle 客户端版本 10g 位于 c oracle 以连接到位于其他国家 地区的数据库 所以我们只能连接到它并且对它的访问权限有限 路径 gt
  • 浏览多个字段的值并将它们插入到同一列中

    我正在尝试使用重复行为我的 oracle apex 应用程序创建一个功能 假设我有一个车辆表 CREATE TABLE vehicles brand VARCHAR2 50 model VARCHAR2 50 comment VARCHAR
  • SQL Fiddle 输出错误

    其实我对 PL SQL 还很陌生 我在 SQL Fiddle 中使用 oracle pl sql 创建了下表 create table Employee name varchar2 100 id integer salary integer
  • 如何在 Pro*C 查询中指定变量表达式列表?

    我尝试优化的 Pro C 查询出现问题 解释一下 我们的应用程序在一个巨大的数据库中搜索行 这些行存在于多种语言中 旧代码为数组中的每种语言选择一行 现在 由于这些查询是我们应用程序中最耗时的部分 因此我只想进行一个直接写入数组的查询 语言
  • 如何从oracle存储过程中提取out变量?

    我有存储过程 其中有很多输出变量 所以我这样调用存储过程 export const infoHR3 async gt try const sql Declare ln order qty NUMBER ln in proc qty hr N
  • 查看oracle中重复行的所有数据

    我有一个有 6 列的表 id name type id code lat long 前三个是必需的 ID是私钥 按序列自动插入 我有一些重复的行 正如两者所定义的name and type id是平等的 但我想查看受骗者的所有数据 我可以很
  • DBMS_SCHEDULER.DROP_JOB 仅当存在时

    我有一个 sql 脚本 在导入转储后必须运行该脚本 该脚本除了执行其他操作外 还执行以下操作 BEGIN remove program SYS DBMS SCHEDULER DROP PROGRAM program name gt STAT
  • 如何在Oracle中将“(Ab56.12345)some_string”的一个字符串列拆分为两列“Ab.12345”,“some_string”

    正如问题一样 如何拆分一个字符串列 Ab56 12345 some string到两列Ab56 12345and some string在甲骨文中 注意 并非所有列都 Ab56 12345 some string 部分列仅some stri
  • 创建和删除表空间 Oracle

    我已经创建了这个表空间 CREATE TABLESPACE IA643 TBS DATAFILE IA643 dat SIZE 500K AUTOEXTEND ON NEXT 300K MAXSIZE 100M 我尝试使用此命令删除它 DR
  • 调整 Oracle 数据库以加快启动速度(闪回)

    我正在使用 Oracle 数据库 11 2 我有一个场景 我发出FLASHBACK DATABASE经常 似乎有一个FLASHBACK DATABASECycle 会重新启动数据库实例 大约需要 1 分钟 我的设置花了 7 秒 数据库很小
  • 从 C# 使用 Odbc 调用 Oracle 包函数

    我在 Oracle 包中定义了一个函数 CREATE OR REPLACE PACKAGE BODY TESTUSER TESTPKG as FUNCTION testfunc n IN NUMBER RETURN NUMBER as be
  • 如何使用 JSON_TABLE 从 Oracle JSON 列获取键值作为结果集

    我用谷歌搜索了很多 似乎无法找到适合我的简单用例的简单解决方案 我在 Oracle 12C 数据库中有一个 json 列 当然实际上是一个带有 json 约束的 varchar 在该列中我存储了这样的 Map 表示 a 9 0847 b 8

随机推荐