从大表中查找类似值的最佳方法

时间:2011-06-11 16:12:25

标签: mysql sql

我有一个数据库,我在mysql中存储超过1000000个名称。现在我的应用程序的任务有点典型。我不仅搜索数据库中的名称,还查找类似的名称。假设名称输入为christian,则应用程序将显示建议的名称,例如christinechris等。在不使用like的情况下,执行此操作的最佳方式是什么?条款。建议仅针对名称最后部分的更改。

6 个答案:

答案 0 :(得分:5)

如果你想要类似的名字(通过声音)SOUNDEX()之类的东西可以提供帮助:http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_soundex

否则… LIKE 'chri%'似乎对我来说不是一个坏主意?

如果您真的只想要没有LIKE的第一个字符,则可以使用SUBSTRING()

答案 1 :(得分:2)

您可以使用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/en/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',metaphone('chris')),
        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]));
        }
}

答案 2 :(得分:1)

Like通常是一个很好的解决方案,但另一种提高性能的方法可能是创建部分列索引,然后以与前缀相同的长度提交查询。请参阅有关col_name(length)的{​​{3}}。

答案 3 :(得分:0)

我认为你可以使用正则表达式。我不擅长它们但是有一个名为REGEXP的函数可以放在WHERE子句中。看here

答案 4 :(得分:0)

你可以使用SOUNDS LIKE,我认为它应该也很快。

http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#operator_sounds-like

答案 5 :(得分:0)

使用左侧固定的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

在排序列表中查找邻居。