2012-04-28 43 views
3

我刚学关于音位和双音位搜索算法,我有几个问题。根据Metaphone Wiki页面,我发现了一些实现的源代码,特别是MySQL实现。我想用我的测试数据库进行测试,所以我首先导入了metaphone.sql文件(包含双倍metaphone功能)here为什么这个MySQL双重metaphone功能不能正常工作?

现在,我有一个表,国家,有一个所有“名称”列中的国家,例如'阿富汗','阿尔巴尼亚','阿尔及利亚'等等。所以,我首先想要在表格中创建一个新列来存储每个国家的双音节字符串。我跑了下面的代码:

UPDATE country SET NameDM = dm(name) 

一切工作正常。阿富汗的metaphone字符串是'AFKNSTN',阿尔巴尼亚的'ALPN',阿尔及利亚的'ALKR,ALJR'等。“真棒”,我想。

然而,当我试图查询该表,我没有得到结果。每metaphone.sql的作者,我坚持下面的SQL语句的语法:

SELECT Name FROM tblPeople WHERE dm(Name) = dm(@search) 

于是,我改变了这种代码如下:

SELECT * FROM country WHERE dm(name) = dm(@search) 

当然,我改变了“@搜索“到我正在查找的任何搜索字词,但是在每个SQL查询后我都得到了0个结果。

谁能解释一下这个问题?我是否错过了重要的东西,或者我只是误解了Metaphone算法?

谢谢!

+0

链接被破坏。 – 2015-11-16 20:39:06

+0

MySQL(和Python)代码现在位于GitHub上:https://github.com/AtomBoy/double-metaphone – Andrew 2016-05-23 20:30:30

回答

2

采取在核对/字符集/编码仔细看(它可以被下降到列级定义)。排序规定了字符串如何进行比较,但字符集可能意味着使用某种排序规则。也许你的字符串有不同的字符集,导致字符串比较失败。

即使这样也透出

select name, length(name), char_length(name), @search, length(@search), char_length(@search) from tbl 

show variables like 'character%' 

show create table tbl 
+0

感谢您的帮助。我检查了我的'国家'表的结构,'name'列和'NameDM'列都是utf8_bin归类。运行该SELECT查询后,我得到以下结果:[link](http://i.imgur.com/PWGRI.png)另一方面,“show variables”查询返回:[link](http: //i.imgur.com/kvxZU.png)。所以有些字符集是拉丁文而不是utf8。这会影响我的查询吗? – TimeBomb006 2012-04-28 13:43:57

2
SELECT * FROM country WHERE NameDM = dm(@search) 

可能是你想要的到底是什么,所以你不计算每个国家每次你做了搜索时间的DM。你看起来应该可以工作。你可以通过干扰拍摄:

SELECT dm('Albania') 

...应该让你ALPN。现在你得到什么...

SELECT * FROM country WHERE NameDM = 'ALPN' 

+0

关于存储metaphone编码的明智建议。 – APC 2012-12-20 12:52:45

3

当比较dm()输出I使用下面的函数,以允许模糊性的另一水平。直接检查dm('smith') != dm('schmitt')失败了大量的名字,包括我自己的常见拼写错误。

该函数创建一个0.0到1.0之间的匹配权重(我希望),它允许我对每个返回的行进行排名,并选择好处,0.3对于捕捉奇怪的发音是一个相当不错的值,0.5是比较平常的。

dmcompare(dm("boothroyd"), dm("boofreed")) = 0.3
dmcompare(dm("smith"), dm("scmitt")) = 0.5

请注意,这是双音位字符串和,这是性能问题的比较,我的数据库包含了音位列以及原始字符串。

 
    CREATE FUNCTION `dmcompare`(leftValue VARCHAR(55), rightValue VARCHAR(55)) 
     RETURNS DECIMAL(2,1) 
    NO SQL 
    BEGIN 
    --------------------------------------------------------------------------------------- 
    -- Compare two (double) metaphone strings for potential similarlity, i.e. 
    -- dm("smith") != dm("schmitt") :: "SM0;XMT" != "XMT;SMT" 
    -- dmcompare(dm('smith'), dm('schmitt') returns 0,5 
    -- @author: P.Boothroyd 
    -- @version: 0.9, 08/01/2013 
    -- The values here can still be played with 
    -- (c) GNU P L - feel free to share and adapt, but please acknowledge the original code 
    --------------------------------------------------------------------------------------- 
     DECLARE leftPri, leftSec, rightPri, rightSec VARCHAR(55) DEFAULT ''; 
     DECLARE sepPos INT; 
     DECLARE retValue DECIMAL(2,1); 
     DECLARE partMatch BOOLEAN; 

     -- Extract the metaphone tags 
     SET sepPos = LOCATE(";", leftValue); 
     IF sepPos = 0 THEN 
      SET sepPos = LENGTH(leftValue) + 1; 
     END IF; 
     SET leftPri = LEFT(leftValue, sepPos - 1); 
     SET leftSec = MID(leftValue, sepPos + 1, LENGTH(leftValue) - sepPos); 

     SET sepPos = LOCATE(";", rightValue); 
     IF sepPos = 0 THEN 
      SET sepPos = LENGTH(rightValue) + 1; 
     END IF; 
     SET rightPri = LEFT(rightValue, sepPos - 1); 
     SET rightSec = MID(rightValue, sepPos + 1, LENGTH(rightValue) - sepPos); 

     -- Calculate likeness factor 
     SET retValue = 0; 
     SET partMatch = FALSE; 
     -- Primaries equal 50% match 
     IF leftPri = rightPri THEN 
      SET retValue = retValue + 0.5; 
      SET partMatch = TRUE; 
     ELSE 
      IF SOUNDEX(leftPri) = SOUNDEX(rightPri) THEN 
       SET retValue = retValue + 0.3; 
       SET partMatch = TRUE; 
      END IF; 
     END IF; 
     -- Test alternate primary and secondaries, worth 30% match 
     IF leftSec = rightPri THEN 
      SET retValue = retValue + 0.3; 
      SET partMatch = TRUE; 
      IF SOUNDEX(leftSec) = SOUNDEX(rightPri) THEN 
       SET retValue = retValue + 0.2; 
       SET partMatch = TRUE; 
      END IF; 
     END IF; 
     -- Test alternate primary and secondaries, worth 30% match 
     IF leftPri = rightSec THEN 
      SET retValue = retValue + 0.3; 
      SET partMatch = TRUE; 
      IF SOUNDEX(leftPri) = SOUNDEX(rightSec) THEN 
       SET retValue = retValue + 0.2; 
       SET partMatch = TRUE; 
      END IF; 
     END IF; 
     -- Are secondary values the same or both NULL 
     IF leftSec = rightSec THEN 
      -- No secondaries ... 
      IF leftSec = '' THEN 
       -- If there is prior matching then no secondaries is 40% 
       IF partMatch = TRUE THEN 
        SET retValue = retValue + 0.4; 
       END IF; 
      ELSE 
       -- If the secondaries match then 50% match 
       SET retValue = retValue + 0.5; 
      END IF; 
     ELSE 
      IF SOUNDEX(leftSec) = SOUNDEX(rightSec) THEN 
       IF leftSec = '' THEN 
        IF partMatch = TRUE THEN 
         SET retValue = retValue + 0.3; 
        END IF; 
       END IF; 
      END IF; 
     END IF; 
     RETURN (retValue); 
    END 

请随时个代码中使用,也请注明来源为这个代码P.Boothroyd任何用途 - 即改变价值观念等

干杯,保罗