2012-04-28 60 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任何用途 - 即改變價值觀念等

乾杯,保羅

相關問題