0

我正在使用 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 的实现,用于 /generating/ Double-Metaphone 值,但是一旦有了这些值,就没有关于如何有效地实际查询数据库的信息。

概括:

当我同时按姓氏和名字搜索时——我想在数据库中查询双变位词匹配只在姓氏上,但是当名字也被传入时,我希望有很大的灵活性..第一个首字母?听上去像 ?等等。我愿意接受建议和 SQL 示例!

更新 1: 当我说我对结果不满意时.. 我的意思是我不确定如何制定查询的 Firstname 部分,以最大化结果。如果我搜索“WILL” - 应该返回什么结果?WILLIAM, WILL, WILBERT .. 但不是 WALKER - 虽然我在这里有什么,WALKER 会被退回,因为 WILL -> FL 和 WALKER 是 [FLKR] 但 WILLIAM 是 [FLM]。如果我只做 DM = DM,那么我什至不会返回 WILLIAM,这就是为什么我首先要做一个 LIKE,如果 DM 长度小于 4。

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

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

4

2 回答 2

0

由您决定您的业务规则关于返回什么,以及考虑使用 LIKE 与 DM(或两者)。

您似乎没有考虑过的事情是 DM 值的长度。

如果我搜索“WILL” - 应该返回什么结果?WILLIAM, WILL, WILBERT .. 但不是 WALKER - 虽然我在这里有什么,WALKER 会被退回,因为 WILL -> FL 和 WALKER 是 [FLKR] 但 WILLIAM 是 [FLM]。如果我只做 DM = DM,那么我什至不会返回 WILLIAM,这就是为什么我首先要做一个 LIKE,如果 DM 长度小于 4。

因此,对于这种情况:

WILL -> FL 和 WALKER 是 [FLKR] 但 WILLIAM > IS [FLM]

假设您可以返回多个匹配,最佳匹配位于顶部,您将按存储的匹配 DM 值升序对结果进行排序。所以,WALKER 会在 WILLIAM 之前被推荐。

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

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

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

于 2012-09-12T19:59:12.087 回答
0

只是为了给您带来另一个麻烦,;-),Bill 也是 William 的缩写。

我对这个主题的想法是,最好将可以缩写或缩写的名称视为与语音匹配不同的问题。一旦你想出了缩写的解决方案,然后通过变音器提供结果。

于 2013-12-26T16:21:03.987 回答