【问题标题】:How can I use ~ to fuzzy match two fields of a table?如何使用 ~ 模糊匹配表的两个字段?
【发布时间】:2019-09-03 13:09:11
【问题描述】:
我正在尝试对包含相同公司信息的两个表执行联接,但有时这些公司存储的名称略有不同(例如表 1:公司 X -> 表 2:公司 X 和朋友)。
我的想法是将表 1 的每一行与表 2 的每一行完全连接,然后使用 ~ 进行过滤(例如 where name1 ~ name2 或 name2 ~ name1),但这是不可能的。
有人有解决这个匹配问题的方法吗?
谢谢!
【问题讨论】:
标签:
postgresql
join
string-matching
similarity
fuzzy
【解决方案1】:
您可以使用“”运算符或pg_trgm提供的'%'运算符进行模糊字符串匹配。
您必须做出决定,例如您愿意为 '%' 使用什么相似性截止值(如果最佳匹配低于该值,则不返回匹配项)以及是否只想返回顶部匹配项(横向连接对此很有用) 或可能不止一个。
最好使用它来清理您的数据,而不是直接将其合并到生产应用程序中。
您可能还需要去掉讨厌的词。 “X 公司和朋友”与“Y 公司和朋友”更相似,而不是“X 公司有限”。
SELECT t1.*, t2.*, 1- (t1.name <-> t2.name) as similarity
FROM table1 t1
INNER JOIN table2 t2
ON t1.name % t2.name
order by t1.name <-> t2.name;
【解决方案2】:
您可以加入,条件是任一名称字段是另一个名称字段的子字符串:
SELECT t1.*, t2.*
FROM table1 t1
INNER JOIN table2 t2
ON t1.name LIKE '%' || t2.name || '%' OR
t2.name LIKE '%' || t1.name || '%';
这种方法甚至不需要正则表达式。我们可以在这里使用正则表达式,如果我们想确保一个表的名称仅作为另一个名称的子字符串出现 并且 也是一个单词。但是,也许您甚至不需要这样做。
【解决方案3】:
你可以
CREATE EXTENSION pg_trgm;
并使用它在连接条件中提供的相似性运算符:
t1 JOIN t2 ON t1.name % t2.name