2

想象一下我有这张桌子:

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 的 fn_Lev 值与表中的所有其他 strTitle 并删除行彼此相似,Levenshtein 距离为 3,宁愿保持更高的 intWeights?

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

1   Item One    7
4   Item Two v1 7

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

干杯,马特

4

2 回答 2

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 的结果来选择要删除的内容。

于 2012-09-27T13:06:04.467 回答
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<->B 是匹配项,则 B<->A 不是。

case语句选择权重最高的结果

于 2012-09-27T13:18:04.177 回答