SQL Server 中的单词匹配

Posted

技术标签:

【中文标题】SQL Server 中的单词匹配【英文标题】:Word matching in SQL Server 【发布时间】:2011-07-26 23:27:13 【问题描述】:

我需要在两个数据库表中的数据之间提供建议的匹配。基本要求是; - 应该为所讨论的两列之间的最多匹配词(不考虑顺序)建议“匹配”。

例如,给定数据;

   Table A                           Table B
1,'What other text in here'      5,'Other text in here'
2,'What am I doing here'         6,'I am doing what here'
3,'I need to find another job'   7,'Purple unicorns'
4,'Other text in here'           8,'What are you doing in here'

Ideally, my desired matches would look as follows;
1 -> 8   (3 words matched)
2 -> 6   (5 words matched)
3 -> Nothing
4 -> 5   (4 words matched)

我发现 word count functions 看起来很有希望,但我想不出如何在 SQL 语句中使用它,这将给我我想要的匹配。此外,链接函数并不是我所需要的,因为它使用 charindex,我认为它在一个词中搜索一个词(即“in”将匹配“bin”)。

谁能帮我解决这个问题?

谢谢。

【问题讨论】:

3 匹配 6。两者都有单词“I”。 1 匹配 5 好于 8。它们有 4 个共同点。 你是对的,但我忘了说比赛中不应该有重复。一旦给定的行匹配,就不能再次匹配。 5 匹配 8 也是对的,但正如我刚刚评论你的答案,理想情况下应该考虑到匹配的整体单词的百分比。 【参考方案1】:

我使用下面的sys.dm_fts_parser句子拆分为单词。 plenty of TSQL split functions around 如果您不在 SQL Server 2008 上或发现由于某种原因不适合使用。

每个A.id 只能与以前未使用过的B.id 配对,反之亦然,这不是我能想到的有效的基于集合的解决方案。

;WITH A(Id, sentence) As
(
  SELECT 1,'What other text in here'    UNION ALL
  SELECT 2,'What am I doing here'       UNION ALL 
  SELECT 3,'I need to find another job' UNION ALL 
  SELECT 4,'Other text in here'         
),
B(Id, sentence) As
(
 SELECT  5,'Other text in here'          UNION ALL
 SELECT  6,'I am doing what here'        UNION ALL
 SELECT  7,'Purple unicorns'             UNION ALL
 SELECT  8,'What are you doing in here'
),  A_Split
     AS (SELECT Id AS A_Id,
                display_term,
                COUNT(*) OVER (PARTITION BY Id) AS A_Cnt
         FROM   A
                CROSS APPLY 
                   sys.dm_fts_parser('"' + REPLACE(sentence, '"', '""')+'"',1033, 0,0)),

     B_Split
     AS (SELECT Id AS B_Id,
                display_term,
                COUNT(*) OVER (PARTITION BY Id) AS B_Cnt
         FROM   B
                CROSS APPLY 
                   sys.dm_fts_parser('"' + REPLACE(sentence, '"', '""')+'"',1033, 0,0)),
     Joined
     As (SELECT A_Id,
                B_Id,
                B_Cnt,
                Cnt = COUNT(*),
                CAST(COUNT(*) as FLOAT)/B_Cnt AS PctMatchBToA,
                CAST(COUNT(*) as FLOAT)/A_Cnt AS PctMatchAToB
         from   A_Split A
                JOIN B_Split B
                  ON A.display_term = B.display_term
         GROUP  BY A_Id,
                   B_Id,
                   B_Cnt,
                   A_Cnt)
SELECT IDENTITY(int, 1, 1) as id, *
INTO   #IntermediateResults
FROM   Joined
ORDER  BY PctMatchBToA DESC,
          PctMatchAToB DESC

DECLARE @A_Id INT,
        @B_Id INT,
        @Cnt  INT

DECLARE @Results TABLE (
  A_Id INT,
  B_Id INT,
  Cnt  INT)

SELECT TOP(1) @A_Id = A_Id,
              @B_Id = B_Id,
              @Cnt = Cnt
FROM   #IntermediateResults
ORDER  BY id

WHILE ( @@ROWCOUNT > 0 )
  BEGIN

      INSERT INTO @Results
      SELECT @A_Id,
             @B_Id,
             @Cnt

      DELETE FROM #IntermediateResults
      WHERE  A_Id = @A_Id
              OR B_Id = @B_Id

      SELECT TOP(1) @A_Id = A_Id,
                    @B_Id = B_Id,
                    @Cnt = Cnt
      FROM   #IntermediateResults
      ORDER  BY id
  END

DROP TABLE #IntermediateResults

SELECT *
FROM   @Results
ORDER  BY A_Id  

返回

A_Id        B_Id        Cnt
----------- ----------- -----------
1           8           3
2           6           5
4           5           4

【讨论】:

哇!我认为一个人对 SQL 了解一两件事,但您刚刚指出有很多我不知道的事情 :) 这当然很有帮助。我忘记提到的一件事是比赛中不应该有重复。实际上,匹配词的百分比最高的匹配应该优先。这就是为什么在我的示例中,我将 4 匹配到 5,因为文本相等(100% 匹配),因此留下 1 与 8 匹配,因为它是下一个最佳匹配。不过我真的很喜欢你的回答。这是很好的思考食物。为你 +1....如果我有任何声誉。 @Mr Moose:你不是吗? :) @Martin:虽然已经声明一行只能匹配一次,但我仍然认为您的解决方案很有用。即使你不打算重做它,它也是一个很好的开始。 @Andriy - 谢谢。我可能会重做它。很容易做到ROW_NUMBER() OVER (PARTITION BY A_Id ... 获得每个 A 的 TOP 1。ROW_NUMBER() OVER (PARTITION BY B_Id ... 获得每个 B 的 TOP 1 但它在将两者结合起来的好方法时让我无法理解。 非常感谢这么棒的答案。我真的很感激你付出的努力。我现在将针对一些测试数据(每个表数百条记录)运行它并查看它的执行情况。现在我可以为你 +1(感谢@Andriy M 指出这一点。)

以上是关于SQL Server 中的单词匹配的主要内容,如果未能解决你的问题,请参考以下文章

查询匹配列表 SQL Server 中的所有记录

如何从 SQL Server 中的表中获取不匹配的数据

SQL Server:具有多个可能条件的案例语句中的模式匹配

sql server如何精准匹配字符中的字符

DateTime格式与SQL SERVER 2012中的预期格式不匹配

C# 查询 SQL Server 表中的 JSON 列以获取匹配的行