MySql匹配最具体的人的名字

时间:2014-02-28 05:04:42

标签: php mysql

我在MySql表中搜索特定人的可能匹配项。我正在使用许多其他标准,但我们假设我们只是谈论给定的名称字段。

假设搜索值是John William,并且该表包含4行,其名称值为

John
John William 
John William Henry
John Paul 

前3名可能是合适的人选。我希望搜索返回与我拥有的名称最匹配的那个,在这种情况下是第2行。

原始代码首先使用完整提供的名称进行完全匹配查询。如果没有返回任何记录,则使用所有带有%的名称进行LIKE查询。如果失败则只对第一个名称进行精确搜索。在上面的示例中,第一个查询返回记录2,这是所需的,因此其他查询不会运行。

问题是如果搜索名称是John William Henry George,您可能需要做大约5个查询才能逐渐使搜索不那么具体。另一个问题是搜索值可能是John W,文件可能包含我希望匹配的John William。反之亦然。

是否有某种方法可以执行单个查询以返回最接近的匹配?换句话说,在上面的例子中只返回第2行。

为了最合适,我认为搜索约翰威廉亨利应该匹配:

John William Henry
John William Henry %
John William H
John William H %
John W H
John W H %
John W
John

请注意,John W之后没有%,因为这将匹配不能成为合适人选的John W B.

好的,尝试提高效率的新想法。是否可以使用之间的某些PHP代码查询先前查询的结果。我不期待。伪代码如下:

$coarse = Mysql search for John%
$count = mysql_num_rows($coarse);
if ($count == 1) { 
   $rec = mysql_fetch_row($coarse);
   return $rec[0];
} 
// Assume that produced 50 records. Now want to search within those only instead of millions

$fine = Mysql search within $coarse results for John William% 
$count = mysql_num_rows($fine);
if ($count == 1) { 
   $rec = mysql_fetch_row($fine);
   return $rec[0];
} 

我显然可以在PHP中进行精细搜索但是可以在SQL中进行,或者我可以使用存储过程执行上述操作吗?

4 个答案:

答案 0 :(得分:0)

我创建了一个存储过程。使用IF ELSE,检查EXISTS是否使用NOT IN来排除查询1的条目。

注意:ANSI SQL中有一个EXCEPT运算符,但MySQL不支持它,因此您使用NOT IN来排除查询行1.

同样不要在数据库/ SQL中加入过多的逻辑...如果你想看到你的名字匹配,我选择一个基本的匹配列表与SQL然后使用PHP代码(与正则表达式)用于'模糊/最佳'匹配或逻辑。

答案 1 :(得分:0)

CREATE PROCEDURE (@u varchar(max))
    BEGIN
        SET @v_counter = CHAR_LENGTH(@u);
        while @v_counter >0 do
            if (Select count(*) from table where firstName like @u+"%")>0
                @v_counter=0
            else
                Begin
                   @u=substr(@u, 0, -1)
                   @v_counter=char_length(u)
                END            
         end while
SELECT * from table where firstName like @u+"%"
Return
END;

这是未经测试的,但应该让你到达目的地。这是一个以全名开头的过程,一次删除一个字符以检查第一个匹配的结果。

答案 2 :(得分:0)

也许尝试不同的方法。请查看MySQLs fulltext search capabilities

让我先给你一个简单的例子。让我们说你的表看起来像这样:

 CREATE TABLE people (
     id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
     fullname TEXT,
     FULLTEXT (fullname)
 ) ENGINE=InnoDB;

然后你可以像这样查询:

SELECT *, 
    MATCH (fullname) AGAINST ('+John William' IN BOOLEAN MODE) AS 'Probability'
FROM people
WHERE MATCH (fullname)
AGAINST ('+John William' IN BOOLEAN MODE)
ORDER BY Probability DESC;

operators可能需要稍加修改才能获得所需的结果。

请记住,要在InnoDB上使用全文索引,您需要更新版本的MySQL。如果没有,则必须使用MyISAM作为引擎。

答案 3 :(得分:0)

我认为最简单的方法是简单地进行一些搜索,从最具体的搜索开始,最不具体的搜索。