检查SQL Server表值对自己

时间:2012-09-27 12:57:13

标签: tsql levenshtein-distance

想象一下,我有这张桌子:

declare @tmpResults table ( intItemId int, strTitle nvarchar(100), intWeight float )

insert into @tmpResults values (1, 'Item One', 7)
insert into @tmpResults values (2, 'Item One v1', 6)
insert into @tmpResults values (3, 'Item Two', 6)
insert into @tmpResults values (4, 'Item Two v1', 7)

一个函数,我们称之为fn_Lev,它接受两个字符串,将它们相互比较,并将它们之间的差异数作为整数(即​​Levenshtein距离)返回。

查询该表的最有效方法是什么,检查每个strTitle对表中所有其他strTitle的fn_Lev值,并且删除行彼此相似Levenshtein距离为3,更喜欢保持更高的intWeights?< / p>

所以在删除之后,@ tmpResults应该包含

1   Item One    7
4   Item Two v1 7

我可以想办法做到这一点,但没有什么不是非常缓慢(即迭代)。我确定有更快的方法吗?

干杯, 马特

2 个答案:

答案 0 :(得分:3)

如果我理解正确,您可以使用交叉连接

SELECT t1.intItemId AS Id1, t2.intItemId AS Id2,  fn_Lev(t1.strTitle, t2.strTitle) AS Lev
FROM @tmpResults AS t1
CROSS JOIN @tmpResults AS t2

交叉连接将为您提供连接左侧和右侧之间的每个行组合的结果(因此它不需要任何ON子句,因为它将所有内容与其他所有内容进行匹配)。然后,您可以使用SELECT的结果来选择要删除的内容。

答案 1 :(得分:3)

SELECT strvalue= CASE 
                WHEN t1.intweight >= t2.intweight THEN t1.strtitle 
                ELSE t2.strtitle 
              END, 
       dist = Fn_lev(t1.strtitle, t2.strtitle) 
FROM   @tmpResults AS t1 
       INNER JOIN @tmpResults AS t2 
         ON t1.intitemid < t2.intitemid 
WHERE  Fn_lev(t1.strtitle, t2.strtitle) = 3 

这将执行仅与每行匹配一次的自联接。它将排除自身匹配或前一匹配的反向,即如果A&lt; - &gt; B是匹配,则B&lt; - &gt; A不匹配。

case语句选择最高加权结果