【问题标题】:SQL Left Fuzzy Join with Levenshtein DistanceSQL Left Fuzzy Join with Levenshtein Distance
【发布时间】:2021-06-27 17:52:16
【问题描述】:

我有两个来自两个不同系统的数据集在 SQL 中合并在一起,但是,这两个系统的命名约定略有不同。约定的变化在较大的数据样本中并不一致,但通常需要进行一次修改才能匹配。

System 1 data System 2 data
AA0330 AA_330
AA0340 AA_340
AA0331 AA_331
AA0341 AA-341

我一直在使用下面的 Levenshtein 距离 SQL 函数太模糊匹配并得到下面的结果,但是,最终得到了重复的连接。我该如何修改我的代码来缓解这种情况?

SELECT [System1].[mvmt1],
       [System2].[mvmt2]       
FROM [System1]
left join [System2] 
     ON dbo.ufn_levenshtein([System1].[mvmt1], [System2].[mvmt2]) < 2;

http://www.artfulsoftware.com/infotree/qrytip.php?id=552&m=0

当前输出:

System 1 data System 2 data
AA0330 AA_330
AA0330 AA_340
AA0340 AA_340
AA0331 AA_331
AA0341 AA-341

如何确保我只能从加入中获得一个结果?

【问题讨论】:

  • 然后看函数,在select中包含函数看看返回什么
  • 该函数只是将 levenshtein 关系作为 int 返回。然后我在我的左连接中使用它。如何让左连接只返回类似于 vlookup 的第一个匹配项?
  • 即使使用左连接,您也可以根据 func 的结果匹配表 a 和 b,因此表 a 中 AA0330 与表 b 中 (AA_330, AA_340) 之间的 Levenshtein 距离小于 2 和这就是为什么你在那里有 2 个结果
  • 谢谢,我是否可以在同一个查询中清理表以只返回一个结果?几乎是系统1的一组??
  • Levenshtein 并不是真正适合这项工作的工具,正如您所发现的那样。我也无法想象它的性能非常好。更好的选择是使用(根据您的样本)前 2 个和后 3 个字符。或者您可以使用嵌套替换,直到一侧适合另一侧的格式。

标签: sql left-join ssms levenshtein-distance fuzzyjoin


【解决方案1】:

不是最好的解决方案,但您可以比较前 2 个字符和后 3 个字符,如果所有代码都遵循相同的模式(右侧 2 个字符,末尾 3 个数字):

SELECT [System1].[mvmt1],
       [System2].[mvmt2]       
FROM [System1]
inner join [System2] 
     ON left(mvmt1,2) = left(mvmt2,2) 
     and right(mvmt1,3) = right(mvmt2,3)

【讨论】:

    【解决方案2】:

    这样的事情怎么样(抱歉格式不好):

    WITH Initial_Fuzzy_Join as(
    SELECT [System1].[mvmt1],
           [System2].[mvmt2]       ,
    dbo.ufn_levenshtein([System1].[mvmt1], [System2].[mvmt2]) as StringDistanceMetric
    FROM [System1]
    left outer join [System2] 
         ON dbo.ufn_levenshtein([System1].[mvmt1], [System2].[mvmt2]) < 2
    )
    SELECT mvmt1, mvmt2, max(StringDistanceMetric)
    FROM Initial_Fuzzy_Join
    Group by mvmt1,mvmt2
    

    【讨论】:

    • 您能否使用更好的格式并解释一下 sql 的作用?