问题描述
|
我有一个数据库,我在其中存储超过1000000个名称。现在,我的应用程序的任务有点典型。我不仅在数据库中搜索名称,还找到相似的名称。假设名称输入为“ 0”,那么应用程序将显示建议的名称,例如“ 1”,“ 2”等。不使用“ 3”子句的最佳方式是什么。建议仅针对名称最后部分的更改。
解决方法
如果您还想要类似的名称(声音),例如
SOUNDEX()
可能会有所帮助:http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_soundex
否则,对我来说,… LIKE \'chri%\'
不是一个坏主意吗?
如果您确实只希望没有LIKE
的前几个字符,则可以使用SUBSTRING()
。
, 您可以使用php \的metaphone()函数为每个名称生成metaphone代码,并将它们与名称一起存储。
<?php
print \"chris\" . \"\\t\" . metaphone(\"chris\") . \"\\n\";
print \"christian\" . \"\\t\" . metaphone(\"christian\") . \"\\n\";
print \"christine\" . \"\\t\" . metaphone(\"christine\") . \"\\n\";
# prints:
# chris XRS
# christine XRSTN
# christian XRSXN
然后,您可以使用levenshtein距离算法(在php [http://php.net/manual/zh/function.levenshtein.php]中或mysql [http://www.artfulsoftware.com/infotree/queries.php# 552]),以计算元代码之间的距离。在我的测试中,距离小于等于2似乎表明您正在寻找相似度。
<?php
$names = array(
array(\'mike\',metaphone(\'mike\')),array(\'chris\',metaphone(\'chris\')),array(\'chrstian\',metaphone(\'christian\')),array(\'christine\',metaphone(\'christine\')),array(\'michelle\',array(\'mick\',metaphone(\'mick\')),array(\'john\',metaphone(\'john\')),array(\'joseph\',metaphone(\'joseph\'))
);
foreach ($names as $name) {
_compare($name);
}
function _compare($n) {
global $names;
$name = $n[0];
$meta = $n[1];
foreach ($names as $cname) {
printf(\"The distance between $name and {$cname[0]} is %d\\n\",levenshtein($meta,$cname[1]));
}
}
, Like
通常是一个很好的解决方案,但是另一种提高性能的方法可能是创建部分列索引,然后以与前缀相同的长度提交查询。请参阅有关regarding11的MySQL文档。
, 我认为您可以使用常规的专家。我不太了解,但是可以在WHERE子句中添加一个名为REGEXP的函数。看这里
, 您可以使用SOUNDS LIKE,我认为它也应该非常快。
http://dev.mysql.com/doc/refman/5.0/zh-CN/string-functions.html#operator_sounds-like
, 在左侧固定的地方使用LIKE不需要进行表格扫描。我假设这就是为什么您不想使用LIKE的原因:SELECT * FROM table WHERE name LIKE CONCAT(?,\"%\")
速度很快,不需要表格扫描即可查找行。 CONCAT允许您使用带有%语法的准备好的查询。
您还可以执行以下操作:
SELECT * from table WHERE name < \'christian\' LIMIT 20
和
SELECT * FROM table WHERE name > \'christian\' LIMIT 20
在排序列表中查找邻居。