Mysql - 按标记化字符串搜索

时间:2016-06-07 20:58:39

标签: mysql sql

我有一个简单的请求:按用户名搜索。 不过,想象一下我在数据库上有这些数据:

1 - John Amazing Doe
2 - John Stupid Doe
3 - John Anthony

当我通过" John Doe"进行搜索时,是否有一种简单的方法来搜索具有" john"或" doe"?更好的是,如果我们可以按谁拥有更多匹配进行排名?

由于

2 个答案:

答案 0 :(得分:1)

全文索引和MATCH()是您的最佳选择。也就是说,这是另一种方式:

您可以搜索包含' John'或者' Doe'使用LIKE

SELECT user_name
FROM   users
WHERE  user_name LIKE 'John%' 
OR     user_name LIKE '%Doe'

仅当姓名不会始终以' John'开头时,才使用前导和尾随%。或者以“Doe”结尾,否则使用一个。 Double %不会使用user_name

上的任何索引

然后,您可以使用UNION和排序列对这些进行排名:

    SELECT user_name, 1 as Sort_Col
    FROM   users
    WHERE  user_name LIKE 'John%' 
    AND    user_name LIKE '%Doe'
UNION
    SELECT user_name, 2 as Sort_Col
    FROM   users
    WHERE (user_name LIKE 'John%' 
    OR     user_name LIKE '%Doe')
    AND    user_name NOT IN (
               SELECT user_name
               FROM   users
               WHERE  user_name LIKE 'John%' 
               AND    user_name LIKE '%Doe')
    ORDER BY Sort_Col ASC

您必须在第二个查询中使用烦人的NOT IN,以确保您不会返回同时包含“John'和' Doe'。通常情况下UNION就足够了,但由于我们添加了Sort_Col,因此不会。只是在可能的情况下添加全文索引的另一个原因。

答案 1 :(得分:1)

在构建查询之前准备数据

这是在发送到MySQL之前以编程方式处理的最佳方法。

将名称转换为列表,中断空格:

  • "John Doe" --> "John|Doe"
  • SELECT username FROM users WHERE username RLIKE'John | Doe'

这里注意sql注入。

php示例

$db = new PDO([conn info]);

$searchArg = 'John Doe';
$nameRegex = str_replace(' ','|', strtolower($searchArg));

$userSearch = $db->prepare('SELECT username FROM users WHERE LOWER(username) REGEXP :nameRegex');
$userSearch->bindValue(':nameRegex', $nameRegex, PDO::PARAM::STR);
$userSearch->execute();

foreach ( $userSearch->fetchAll(PDO::FETCH_ASSOC) as $user ) {
    echo $user['username'] . '\n<br>';
}