【问题标题】:SQL Fuzzy MatchingSQL 模糊匹配
【发布时间】:2013-11-19 06:11:39
【问题描述】:

希望我不要重复这个问题。在发帖之前,我在这里和谷歌上做了一些搜索。

我正在使用启用全文的 SQL Server 2008R2 运行 eStore。

我的要求,

  1. 有一个产品表,其中包含产品名称、OEM 代码、该产品适合的型号。都是文字。
  2. 我创建了一个名为 TextSearch 的新列。这具有该产品适合的产品名称、OEM 代码和型号的串联值。这些值以逗号分隔。
  3. 当客户输入关键字时,我们会在 TextSearch 列上运行搜索以匹配产品。请参阅下面的匹配逻辑。

我正在使用混合全文和正常的搜索。这给出了更相关的结果。所有在临时表中执行的查询和不同的都被返回。

匹配逻辑,

  1. 运行以下 SQL 以使用全文获取相关产品。但@Keywords 将被预处理。假设“CLC 2200”将更改为“CLC* AND 2200*”

    SELECT Id FROM dbo.Product WHERE CONTAINS (TextSearch ,@Keywords)

  2. 另一个查询将使用正常的like运行。所以'CLC 2200'将被预处理为'TextSearch like %clc% AND TextSearch like %2200%'。这仅仅是因为全文搜索不会在关键字之前搜索模式。例如,它不会返回 'pclc 2200'。

    SELECT Id FROM dbo.Product WHERE TextSearch like '%clc%' AND TextSearch like '%2200%'

  3. 如果第 1 步和第 2 步没有返回任何记录,将执行以下搜索。我对值 135 进行了微调,以返回更多相关记录。

    SELECT p.id FROM dbo.Product AS p INNER JOIN FREETEXTTABLE(product,TextSearch,@Keywords) AS r ON p.Id = r.[KEY] WHERE r.RANK > 135

以上所有组合都能以合理的速度正常运行,并为关键字返回相关产品。

但是当根本没有找到产品时,我正在寻求进一步改进。

假设客户在寻找“CLC 2200npk”但该产品不存在,我需要显示下一个非常接近“CLC 2200”的产品。

到目前为止,我尝试使用 Soundex() 函数。购买计算 TextSearch 列中每个单词的 soundex 值,并与关键字的 soudex 值进行比较。但这会返回太多记录,而且速度也很慢。

例如,“CLC 2200npk”将返回“CLC 1100”等产品。但这不是一个好的结果。因为它不接近 CLC 2200npk

还有一个不错的here。但这使用 CLR 函数。但是我无法在服务器上安装 CLR 功能。

所以我的逻辑应该是,

如果未找到“CLC 2200npk”,则在“CLC 2200”旁边显示 如果未找到“CLC 2200”,则在“CLC 1100”旁边显示下一个关闭

问题

  1. 是否可以按照建议进行匹配?
  2. 如果我需要进行拼写更正和搜索,有什么好的方法?我们所有的产品列表都是英文的。
  3. 是否有任何 UDF 或 SP 来匹配我的建议之类的文本?

谢谢。

【问题讨论】:

    标签: sql-server sql-server-2008 full-text-search fuzzy-search


    【解决方案1】:

    一个相当快速的特定领域解决方案可能是使用 SOUNDEX 和 2 个字符串之间的数字距离来计算字符串相似度。只有当您有很多产品代码时,这才会真正有帮助。

    使用像下面这样的简单 UDF,您可以从字符串中提取数字字符,这样您就可以从“CLC 2200npk”中获得 2200,从“CLC 1100”中获得 1100,因此您现在可以根据 SOUNDEX 输出确定接近度每个输入的距离以及每个输入的数字分量的接近度。

    CREATE Function [dbo].[ExtractNumeric](@input VARCHAR(1000))
    RETURNS INT
    AS
    BEGIN
        WHILE PATINDEX('%[^0-9]%', @input) > 0
        BEGIN
            SET @input = STUFF(@input, PATINDEX('%[^0-9]%', @input), 1, '')
        END
        IF @input = '' OR @input IS NULL
            SET @input = '0'
        RETURN CAST(@input AS INT)
    END
    GO
    

    就通用算法而言,根据数据集大小和性能要求,有几个可能会帮助您获得不同程度的成功。 (两个链接都有可用的 TSQL 实现)

    • Double Metaphone - 这个算法会给你一个比 soundex 更好的匹配,但它确实有利于拼写校正。
    • Levenshtein Distance - 这将计算将一个字符串转换为另一个字符串所需的按键次数,例如从“CLC 2200npk”到“CLC 2200”为 3,而从“CLC 2200npk”到“CLC 1100”为 5。

    Here 是一篇有趣的文章,它将两种算法结合在一起,可能会给你一些想法。

    希望其中的一些帮助会有所帮助。

    编辑:Here 是一种更快的部分 Levenshtein 距离实现(阅读帖子,它不会返回与正常结果完全相同的结果)。在我的 125000 行测试表上,它在 6 秒内运行,而我链接到的第一个表运行时间为 60 秒。

    【讨论】:

    • Levenshtein Distance 似乎通过搜索栏重建效果很好。它也可以容忍一些拼写错误。感人的。有点缺点是,它似乎需要一些时间来运行。我正在寻求改进。还检查了您的 ExtractNumeric UDF,但这并没有产生足够的变体来精确匹配。标记为答案。杰亚拉。
    • 刚刚进行了编辑以包含更快的 Levenshtein Distance 实现,这应该有助于缩短运行时间。
    • 感谢改进的 Levenshtein Distance 实施。已修复,现已投入生产。
    • Levenshtein 距离函数如果实现为 CLR 函数可能会更好。例如,我在 C# 中创建了一个 Damerau-Levenshtein 函数,我将其用作 SQL Server 中的 CLR 函数。它针对 125000 个表行的搜索字符串计算距离,总时间为亚秒级。
    • 最后两个链接失效了!
    猜你喜欢
    • 2021-10-05
    • 2014-10-15
    • 1970-01-01
    • 2010-10-29
    • 2016-02-11
    • 2021-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多