PostgreSQL 模糊匹配
PostgreSQL Fuzzy Matching
我有 2 个表,其中包含以下字段:
- 名字
- 姓氏
- 中间名
- 州
- 邮编
- SSN
- 出生日期
- Phone
我正在尝试查找 2 个表之间匹配的记录和最有可能匹配但由于输入错误、数据缺失、名称拼写差异等原因不完全匹配的记录...
部分数据缺失。但是对于那里的所有数据,两个表的每个数据元素都具有相同的格式/数据类型。
理想情况下,我希望对结果采用某种加权机制。
现在,如果 SSN 是直接匹配项,那么我们就有匹配项了。但我还想考虑是否存在用户输入错误以及混淆了 2 位数字或类似情况。
我在 PG 中有哪些选择?
如果我 运行 多个变体(示例),直接匹配就可以了。
- 社交匹配
- 姓氏、出生日期、邮编
- 姓氏、出生日期、州
- 姓氏、名字、出生日期、邮政编码
不过,我很想部署一个更完整的解决方案,并且正在寻找有关如何进行的任何提示。
我认为 fuzzystrmatch
and/or pg_trgm
模块正是您要找的。
这个叫Probabilistic Record Linkage(其实有好几个名字)
您要做的第一件事是标准化每一列的值,以便它们可以直接比较。例如,日期应为 ISO 格式并经过修整。
简单的方法
统计匹配列数:
select
n.id as needle_id,
h.id as haystack_id,
case when n.col1 = h.col1 then 1 else 0 end
+ case when some_comparison_function(n.col2, h.col2) then 1 else 0 end
+ ...
as relevance
from
needles n
join
haystack h -- haystack table could be the same as needles table
on -- only compare rows where at least one column matches
n.col1 = h.col1
or some_comparison_function(n.col2, h.col2)
or ...
order by
relevance desc;
更难但更正确的方法
这在数学上 proven 是最优的。它根据值的稀有程度为您计算列的权重。
选择两个值应该相等但不同的概率。例如,两条记录应具有相同的 SSN,但出现了拼写错误。一减去这个值就是你的 m-prob
(称之为 99%)。
为每一列计算每个值的相对频率。这是你的 u-prob
对于每个可能的匹配项(needle.dob vs haystack.dob),如果他们同意则计算优势比:m-prob / u-prob
,或者如果他们不同意则计算优势比: (1 - m-prob) / (1 - u-prob)
将所有赔率相乘得到总赔率
计算匹配概率:total_odds / (1 + total_odds)
如果概率超过阈值则匹配,否则不匹配
我有 2 个表,其中包含以下字段:
- 名字
- 姓氏
- 中间名
- 州
- 邮编
- SSN
- 出生日期
- Phone
我正在尝试查找 2 个表之间匹配的记录和最有可能匹配但由于输入错误、数据缺失、名称拼写差异等原因不完全匹配的记录...
部分数据缺失。但是对于那里的所有数据,两个表的每个数据元素都具有相同的格式/数据类型。
理想情况下,我希望对结果采用某种加权机制。
现在,如果 SSN 是直接匹配项,那么我们就有匹配项了。但我还想考虑是否存在用户输入错误以及混淆了 2 位数字或类似情况。
我在 PG 中有哪些选择?
如果我 运行 多个变体(示例),直接匹配就可以了。
- 社交匹配
- 姓氏、出生日期、邮编
- 姓氏、出生日期、州
- 姓氏、名字、出生日期、邮政编码
不过,我很想部署一个更完整的解决方案,并且正在寻找有关如何进行的任何提示。
我认为 fuzzystrmatch
and/or pg_trgm
模块正是您要找的。
这个叫Probabilistic Record Linkage(其实有好几个名字)
您要做的第一件事是标准化每一列的值,以便它们可以直接比较。例如,日期应为 ISO 格式并经过修整。
简单的方法
统计匹配列数:
select
n.id as needle_id,
h.id as haystack_id,
case when n.col1 = h.col1 then 1 else 0 end
+ case when some_comparison_function(n.col2, h.col2) then 1 else 0 end
+ ...
as relevance
from
needles n
join
haystack h -- haystack table could be the same as needles table
on -- only compare rows where at least one column matches
n.col1 = h.col1
or some_comparison_function(n.col2, h.col2)
or ...
order by
relevance desc;
更难但更正确的方法
这在数学上 proven 是最优的。它根据值的稀有程度为您计算列的权重。
选择两个值应该相等但不同的概率。例如,两条记录应具有相同的 SSN,但出现了拼写错误。一减去这个值就是你的
m-prob
(称之为 99%)。为每一列计算每个值的相对频率。这是你的
u-prob
对于每个可能的匹配项(needle.dob vs haystack.dob),如果他们同意则计算优势比:
m-prob / u-prob
,或者如果他们不同意则计算优势比:(1 - m-prob) / (1 - u-prob)
将所有赔率相乘得到总赔率
计算匹配概率:
total_odds / (1 + total_odds)
如果概率超过阈值则匹配,否则不匹配