用于使用Double Metaphone查询MSSQL的SQL用于名字/姓氏组合的SQL

时间:2012-09-12 19:08:18

标签: sql tsql metaphone

我在我的数据库中使用Double-Metaphone进行模糊搜索。我有一个名字表,并且名字和姓氏都已经创建了两个metaphone条目(并通过Trigger更新)。在我的应用程序中,我允许用户按姓氏和/或名字进行搜索。

查询数据库的最佳方法是什么,在处理姓氏和名字时从Double-Metaphone索引中获得最佳结果?仅基于姓氏查询很容易 - 生成DM标签并查询数据库。在第一次和最后一次查询时,我想进行一些微调。

数据库布局类似于以下内容:

tblName
  FirstName
  LastName
  MetaPhoneFN1
  MetaPhoneFN2
  MetaPhoneLN1
  MetaPhoneLN2

申请:[姓氏] [名字]

用户只输入姓氏,或姓氏+ [首字母,名字,名字的一部分]的组合。

Lastname:  SMITH
FirstName:  J or Jo or John or Johnathan

如果我传入“J”作为名字 - 我希望所有名称条目都匹配“J%”。

如果我传入“JO”作为名字 - 我希望所有名称条目都匹配“JO%”。

如果我传入“JOHN”或“JOHNATHAN”作为名字 - 我想使用DM

或者也许是“JOHN%”?

我真的愿意接受这里的建议,为名字。我希望结果尽可能好,并返回用户想要的内容。

查询数据库中最后一个+任何名字组合的最佳方法是什么?这是我到目前为止所得到的一个样本......我对结果并不十分兴奋:

SELECT *
FROM tblName
WHERE
--There will always be a last name
    (MetaPhoneLN1 = @paramMetaPhoneLN1
OR  (CASE WHEN @paramMetaPhoneLN2 IS NOT NULL AND MetaPhoneLN2 = @paramMetaPhoneLN2 THEN 1
          WHEN @paramMetaPhoneLN2 IS NULL THEN 0
     END) = 1)
--  Match Firstname 1
AND (CASE WHEN @paramMetaPhoneFN1 IS NULL THEN 1                      
          WHEN @paramMetaPhoneFN1 IS NOT NULL AND MetaPhoneFN1 = @paramMetaPhoneFN1 THEN 1                
          WHEN LEN(@paramMetaPhoneFN1) > 1 AND LEN(@paramMetaPhoneFN1) < 4 AND MetaPhoneFN1 LIKE @paramMetaPhoneFN1 + '%' THEN 1
          WHEN LEN(@paramMetaPhoneFN1) = 1 THEN 1                                               
      END) = 1  
--  Match Firstname 2
AND (CASE WHEN @paramMetaPhoneFN2 IS NULL THEN 1
          WHEN @paramMetaPhoneFN2 IS NOT NULL AND MetaPhoneFN2 = @paramMetaPhoneFN2 THEN 1
          WHEN LEN(@paramMetaPhoneFN2) > 1 AND LEN(@paramMetaPhoneFN2) < 4 AND MetaPhoneFN2 LIKE @paramMetaPhoneFN2 + '%' THEN 1
          WHEN LEN(@paramMetaPhoneFN2) = 1 THEN 1           
        --ELSE 0                    
      END) = 1
AND (CASE WHEN @paramFirstName IS NULL THEN 1
          WHEN  FirstName LIKE @paramFirstName + '%' THEN 1                     
        --WHEN LEN(@paramMetaPhoneFN1) = 1 AND @paramFirstName IS NOT NULL AND LEN(@paramFirstName) > 1 AND FirstName LIKE @paramFirstName + '%' THEN 1
      --ELSE 1
END) = 1

我尝试做的是考虑名字的不同变体。然而,我的结果并不完全是我想要的。

我已经能够在SQL / C#等中找到许多用于/生成/ Double-Metaphone值的Double Metaphone实现,但是没有关于如何在有这些值后实际查询数据库的内容。< / p>

概要

当我用lastname和firstname搜索时 - 我想在Lastname上查询数据库中的Double Metaphone匹配,但是当传入firstname时我还要有很大的灵活性。 ?听起来好像 ?我对建议和SQL示例持开放态度!

更新1: 当我说我对结果不感兴趣时​​...我所说的是我不确定如何制定查询的名字部分,以最大化结果。如果我搜索“WILL” - 应该返回什么结果?威廉,威尔,威尔伯特......但不是沃克 - 虽然我在这里有,沃克将会因为威尔而被退回 - &gt; FL和WALKER是[FLKR]但是WILLIAM是[FLM]。如果我只做DM = DM那么我就不会让WILLIAM回来了,这就是为什么我在第一时间做一个LIKE,如果DM长度是&lt; 4。

基本上,我想知道是否有其他人遇到过这个问题,看看其他人提出了什么解决方案。

仅限第一个首字母 - 应显示以该首字母开头的所有firstnames   - 这是我不确定的地方: 部分名称 - 应该是所有以名字开头的名字吗? [你怎么知道这只是一个部分名字?!] 全名 - 应该使用DM?

2 个答案:

答案 0 :(得分:0)

由您自行决定返回的业务规则,以及使用LIKE与DM(或两者)进行考虑的内容。

一旦你似乎没有考虑,尽管是DM值的长度。

  

如果我搜索“WILL” - 应该返回什么结果?威廉,   威尔,威尔伯特......但不是沃克 - 尽管我拥有的东西,沃克   将被退回,因为WILL - &gt; FL和WALKER是[FLKR]但是WILLIAM   是[FLM]。如果我只做DM = DM那么我甚至不会得到WILLIAM   返回,这就是为什么我在第一时间做一个喜欢,如果DM   长度是&lt; 4。

所以,对于这种情况:

  

WILL - &gt; FL和WALKER是[FLKR]但是WILLIAM&gt;是[FLM]

假设您可以在顶部返回多个匹配且匹配最佳的匹配,则可以按存储的匹配DM值的升序长度对结果进行排序。所以,WALKER会在WILLIAM之前被建议。

对于名字,再次假设你可以返回多个可能的匹配,你可以先返回精确的字符串匹配(非DM),然后是精确的DM匹配,然后是最短DM排序的部分DM和LIKE匹配首先匹配,然后LIKE匹配,然后其余的较长DM匹配。这通常是使用一堆UNIONed查询最容易完成的。

您还可以选择根据返回的字符串长度与输入字符串长度的差异(较小的差异=更好的匹配)对LIKE匹配进行排名。

您面临的困难是您正在将搜索缩写名称与发音相似的名称结合起来。这两个目标有时是相互对立的。

答案 1 :(得分:0)

只是为了给你另一个复杂功能,;-),比尔也是威廉的缩写。

我对这个问题的看法是,最好将可能缩写的名称或缩写作为与语音匹配分开的问题。一旦你想出了缩写的解决方案,然后通过metaphone提供结果。