根据 SQL 中两列之间的模糊匹配创建 true/false 列

Create true/false column out of fuzzy matching between two columns in SQL

首先,在详细说明我正在处理的问题之前,让我告诉你,我目前是一个 SQL-新手,所以只要有可能,我都会感谢简单的解释和简单的解决方案。这是我拥有的:

鉴于此查询:

        SELECT 
        table1.id as id, 
        table1.tag1 as tag1, 
        table2.tag2 as tag2,
        table2.tag2 like '%'+table1.tag1'%' as match


        FROM table1
        INNER JOIN table2
        ON table1.id = table2.id

我明白了 table:

id     tag1         tag2           match
1      ice cream    ice-cream      false
2      sweets       sweets         true
3      bakery       bakery         true
4      sweets       ice-cream      false

我要解决的问题是,我希望 "match" 列解释为 "true" 与第一行相似的词。因此,在我想要的输出中,我希望这个提到的单元格是 "true" 而不是 "false"。

提前致谢。

您需要准确决定您想要的匹配项。让我假设 space 可以匹配 任何 字符。然后使用:

table2.tag2 like '%' + replace(table1.tag1, ' ', '_') + '%' as match

或者,您可能希望删除所有 space 和连字符以进行比较:

replace(replace(table2.tag2, ' ', ''), '-', '') like '%' + replace(replace(table1.tag1, ' ', ''), '-', '') + '%'

"Similar" 可以通过多种方式进行估算。有些方法是......精心制作的。一个好的起点是 "edit distance." 这也以其创建者的名字命名为 "Levenshtein distance"。这个想法很容易理解,结果也很有意义。 (这听起来也很像您的要求。)尽管有多种变体,但基本思想是计算将一个字符串转换为另一个字符串需要更改多少个字符。所以 "ice cream" 到 "ice-cream" 需要一个改变。那很接近。 "ice cream" 到 "nice dream" 需要进行更多更改。您可以查找该算法并通过很好的示例找到很多相关信息。言归正传,拼写检查人员传统上把这个算法放在他们的技巧包里。这是他们可以建议具有不同词根的相似词的一种方式。

默认情况下,Levenshtein 在 Postgres 中未启用,但它包含在名为 "fuzzystrmatch":

的标准扩展中

https://www.postgresql.org/docs/current/fuzzystrmatch.html

该扩展还包括一些 "phonetic" 匹配算法,这些算法并不是您所追求的那样。根据您的部署方式,还有另一个带有一堆模糊字符串匹配工具的扩展,但老实说,无论如何我都会从 Levenshtein 开始。

https://github.com/eulerto/pg_similarity

如果您最终使用 RDS,则支持 pg_similarity。

您可能会听到的其他建议包括 LIKE、正则表达式和三字母组合(太棒了!但涉及更多)。

模糊字符串匹配是个大课题,超级有趣。如果你进一步追求这个,它将有助于了解你正在处理的记录计数,你的字符串有多长(较短的字符串更难以模糊比较,因为没有那么多可以使用),你的 Postges 版本等.

@Morris 的回答适合 Postgres。在 Refshift 上,您可以为模糊匹配创建一个 Python UDF,它将 2 个字符串作为输入,并且 returns 可以是二元判断或这些字符串之间的某种相似性度量。这是使用 Python UDF 实现 Levenshtein 算法的一个很好的例子:Periscope community thread

函数returns两个单词之间的字符串"distance"(有多少字符不同)。

您可以将输出用作 levenshtein(table2.tag2,table1.tag1)<=1 as match