为什么不是';这个MySQL双变音功能不能正常工作吗?

为什么不是';这个MySQL双变音功能不能正常工作吗?,mysql,database,algorithm,metaphone,Mysql,Database,Algorithm,Metaphone,我正在学习变音和双变音搜索算法,我有几个问题。在Metaphone Wiki页面上,我找到了两个带有实现的源代码,特别是一个MySQL实现。我想用我的测试数据库来测试它,所以我首先导入了找到的metaphone.sql文件(包含双变音函数) 现在,我有一个表,country,在“name”列中有一个所有国家的列表,例如“阿富汗”、“阿尔巴尼亚”、“阿尔及利亚”等。因此,首先,我想在表中创建一个新列来存储每个国家的双变音字符串。我运行了以下代码: UPDATE country SET NameDM

我正在学习变音和双变音搜索算法,我有几个问题。在Metaphone Wiki页面上,我找到了两个带有实现的源代码,特别是一个MySQL实现。我想用我的测试数据库来测试它,所以我首先导入了找到的metaphone.sql文件(包含双变音函数)

现在,我有一个表,country,在“name”列中有一个所有国家的列表,例如“阿富汗”、“阿尔巴尼亚”、“阿尔及利亚”等。因此,首先,我想在表中创建一个新列来存储每个国家的双变音字符串。我运行了以下代码:

UPDATE country SET NameDM = dm(name)
一切正常。阿富汗的变音字符串是“afknsn”,阿尔巴尼亚的变音字符串是“ALPN”,阿尔及利亚的变音字符串是“ALKR”;“太棒了,”我想

然而,当我试图查询该表时,没有得到任何结果。根据metaphone.sql的作者,我遵循以下sql语句的语法:

SELECT Name FROM tblPeople WHERE dm(Name) = dm(@search)
因此,我将此代码更改为:

SELECT * FROM country WHERE dm(name) = dm(@search)
当然,我将“@search”更改为我要查找的任何搜索词,但在每次SQL查询之后,我都得到了0个结果

有人能解释一下这个问题吗?我是错过了一些重要的东西,还是我只是误解了变音算法


谢谢大家!

仔细查看排序规则/字符集/编码(可以定义到列级别)。排序规则定义字符串的比较方式,但字符集可能意味着使用某种排序规则。可能文字字符串具有不同的字符集,导致字符串比较失败

甚至这也可能是一个启示

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

这可能是您最终想要的,因此您不会每次搜索时都计算每个国家的DM。不过,你所拥有的看起来应该有用。您可以通过以下操作排除故障:

SELECT dm('Albania')
。。。你应该去阿尔卑斯山。现在你得到了什么

SELECT * FROM country WHERE NameDM = 'ALPN'

在比较
dm()
输出时,我使用以下函数来允许进一步的模糊性。直接检查
dm('smith')!=dm('schmitt')
在许多名字上都失败了,包括我自己常见的拼写错误

该函数创建了一个介于0.0和1.0(我希望)之间的匹配权重,它允许我对每个返回的行进行排序,并选择那些有利的行,0.3是捕获奇数发音的一个很好的值,0.5更常见

i、 e。
dmcompare(dm(“boothroyd”)、dm(“boofreed”)=0.3
dmcompare(dm(“smith”)、dm(“scmitt”)=0.5

请注意,这是双变音字符串而不是原始字符串的比较,这是为了性能问题,my DB包含一列变音以及原始字符串

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 创建函数“dmcompare”(leftValue VARCHAR(55),rightValue VARCHAR(55)) 返回十进制(2,1) 无SQL 开始 --------------------------------------------------------------------------------------- --比较两个(双)变音字符串的潜在相似性,即。 --dm(“史密斯”)!=dm(“施密特”):“SM0;XMT”!=“XMT;SMT” --dmcompare(dm('smith'),dm('schmitt')返回0,5 --@作者:P.Boothroyd --@version:0.92013年8月1日 --这里的值仍然可以使用 --(c)GNU P L-欢迎分享和改编,但请确认原始代码 --------------------------------------------------------------------------------------- 声明leftPri、leftSec、rightPri、rightSec VARCHAR(55)默认值“”; 声明sepPos INT; 声明值十进制(2,1); 声明部分匹配布尔; --提取变音标记 设置sepPos=LOCATE(“;”,leftValue); 如果sepPos=0,则 设置sepPos=LENGTH(leftValue)+1; 如果结束; 设置leftPri=LEFT(leftValue,sepPos-1); 设置leftSec=MID(leftValue,sepPos+1,长度(leftValue)-sepPos); 设置sepPos=LOCATE(“;”,rightValue); 如果sepPos=0,则 设置sepPos=LENGTH(rightValue)+1; 如果结束; 设置rightPri=LEFT(rightValue,sepPos-1); 设置rightSec=MID(rightValue,sepPos+1,长度(rightValue)-sepPos); --计算相似系数 设置retValue=0; 设置partMatch=FALSE; --初选相等于50%匹配 如果leftPri=rightPri,则 设置retValue=retValue+0.5; 设置partMatch=TRUE; 其他的 如果SOUNDEX(leftPri)=SOUNDEX(rightPri),则 设置retValue=retValue+0.3; 设置partMatch=TRUE; 如果结束; 如果结束; --测试备用的初级和次级,价值30%匹配 如果leftSec=rightPri,则 设置retValue=retValue+0.3; 设置partMatch=TRUE; 如果SOUNDEX(leftSec)=SOUNDEX(rightPri),则 设置retValue=retValue+0.2; 设置partMatch=TRUE; 如果结束; 如果结束; --测试备用的初级和次级,价值30%匹配 如果leftPri=rightSec,则 设置retValue=retValue+0.3; 设置partMatch=TRUE; 如果SOUNDEX(leftPri)=SOUNDEX(rightSec),则 设置retValue=retValue+0.2; 设置partMatch=TRUE; 如果结束; 如果结束; --辅助值是否相同或都为空 如果leftSec=rightSec,则 --没有二等兵。。。 如果leftSec='',则 --如果之前有匹配,则没有辅助项为40% 如果partMatch=TRUE,则 设置retValue=retValue+0.4; 如果结束; 其他的 --如果二级匹配,则50%匹配 设置retValue=retValue+0.5; 如果结束; 其他的 如果是SOUNDEX(
SELECT dm('Albania')
SELECT * FROM country WHERE NameDM = 'ALPN'
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