MySQL搜索查询在两个不同的字段上

时间:2010-03-18 11:22:08

标签: mysql

我需要使用LIKE函数搜索两个字段,并且也应该以相反的顺序匹配。我的表使用的InnoDB没有全文搜索。

考虑以下情况:

我有一个带有first_name和last_name列的用户表。在它上面,有一行具有以下值:

{
    first_name: 'Ludwig',
    last_name: 'van Beethoven',
}

例:

  1. 可以搜索“Ludwig van Beethoven”
  2. 可以搜索“Beethoven Ludwig”
  3. 可以搜索“Ludwig”
  4. 可以搜索“贝多芬”
  5. 我尝试了这个SQL语句,但没有运气。

    SELECT CONCAT(first_name, ' ', last_name) as fullname 
      FROM users 
     WHERE fullname LIKE '%Ludwig van Beethoven%';
    

4 个答案:

答案 0 :(得分:7)

您需要在where子句中重新声明concat表达式。

 SELECT CONCAT(first_name, ' ', last_name) as fullname 
      FROM users 
     WHERE CONCAT(first_name, ' ', last_name) LIKE '%doe%';

不幸的是“as”只是创建一个列别名,而不是你可以在其他地方使用的变量。

答案 1 :(得分:6)

The Main Thing

确保您在first_namelast_name上有一个复合索引。否则,无论您如何处理此问题,它都非常容易最终进行全表扫描。因此,如果您还没有,请创建一个:

CREATE INDEX users_firstandlast ON users(first_name, last_name);

语法选项

一旦该指数到位,您就有了一些选择:

选项1 :正如Willis Blackburn所述,请重复CONCAT子句中的WHERE(因为AS没有为您创建名称可以在WHERE子句中使用:

SELECT CONCAT(first_name, ' ', last_name) as fullname 
FROM users 
WHERE CONCAT(first_name, ' ', last_name) LIKE '%doe%';

使用EXPLAIN检查您的具体情况,但在我的测试中,它表示它使用复合索引,即使您在WHERE子句中使用了一个函数。

选项2 :在此特定的情况下,您始终可以在LIKE子句中使用两个WHERE

SELECT CONCAT(first_name, ' ', last_name) as fullname 
FROM users 
WHERE first_name LIKE '%doe%' or last_name LIKE '%doe%';

同样,这可以使用复合索引(而不会使用first_namelast_name列上的单个索引 - 如果您没有使用通配符,但根据EXPLAIN [并且您的里程可能会有所不同,请务必检查],在这种情况下,它会与表格扫描一致。)

选项3 his answer中,Andy表示您可以使用HAVING。我的read of the MySQL manual建议它首先构建结果集,然后在发送给客户端之前在最后应用HAVING,所以我对此持怀疑态度。 但是,在我的快速和肮脏的测试中,EXPLAIN告诉我,如果你有上面提到的复合索引,HAVING版本会进行索引搜索,而不是表扫描。如果您使用真实数据进行测试,那么这对您来说可能是一个不错的选择。以这种方式使用HAVING是MySQL扩展(不是标准的),但是再次,CONCAT也是如此,所以我们已经进入了MySQL特定的东西。 :-)但是,再次,仔细检查你的现实生活环境。

结论

如果您还没有索引,请创建索引,如果远程可能,我会使用选项2;否则,选项1除非您能找到(或者Andy可以提供)HAVING没有建立大量中间结果集的参考(如果不是非标准的话,它会非常酷,如果没有的话)。无论如何,请在您的特定环境中查看EXPLAIN并进行测试。

答案 2 :(得分:2)

SELECT * FROM users WHERE CONCAT(first_name,'',last_name)LIKE'%Ludwig%'或CONCAT(last_name,'',first_name)LIKE'%Ludwig%';

所有返回的搜索案例包括“Beethoven Ludwig”。

答案 3 :(得分:-2)

当你CONCAT()两列时,LIKE变得区分大小写。所以这应该找到你的结果,但不是最佳的表现:

SELECT CONCAT(first_name, ' ', last_name) AS fullname FROM users 
WHERE LOWER(CONCAT(first_name, ' ', last_name)) LIKE LOWER('%doe%');

这让MySQL在每一行都可以工作。