我需要使用LIKE函数搜索两个字段,并且也应该以相反的顺序匹配.我的表使用没有全文搜索的InnoDB.
考虑以下情况:
我有一个带有first_name和last_name列的用户表.在它上面,有一行具有以下值:
{
first_name: 'Ludwig',
last_name: 'van Beethoven',
}
Run Code Online (Sandbox Code Playgroud)
案例:
我试过这个SQL语句,但没有运气.
SELECT CONCAT(first_name, ' ', last_name) as fullname
FROM users
WHERE fullname LIKE '%Ludwig van Beethoven%';
Run Code Online (Sandbox Code Playgroud)
您需要在where子句中重新声明concat表达式.
SELECT CONCAT(first_name, ' ', last_name) as fullname
FROM users
WHERE CONCAT(first_name, ' ', last_name) LIKE '%doe%';
Run Code Online (Sandbox Code Playgroud)
不幸的是"as"只是创建一个列别名,而不是你可以在其他地方使用的变量.
请确保你有一个复合索引first_name和last_name.否则,无论您如何处理此问题,最终都可以轻松完成全表扫描.因此,如果您还没有,请创建一个:
CREATE INDEX users_firstandlast ON users(first_name, last_name);
Run Code Online (Sandbox Code Playgroud)
一旦该指数到位,您就有了一些选择:
选项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%';
Run Code Online (Sandbox Code Playgroud)
使用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%';
Run Code Online (Sandbox Code Playgroud)
再次,这可以使用复合索引(而不会使用first_name和last_name列上的单个索引- 如果你没有使用通配符,但是根据EXPLAIN[并且你的里程可能会有所不同,请务必检查) ],在这种情况下,它与表扫描一起).
选项3在他的回答中,安迪说你可以用HAVING它.我阅读MySQL手册表明它将首先构建结果集,然后HAVING才将其发送到客户端之前应用到最后,因此我对此持怀疑态度.但是,在我的快速和肮脏的测试中,EXPLAIN告诉我如果你有上面提到的复合索引,那么HAVING版本会进行索引搜索,而不是表扫描.如果您使用真实数据进行测试,那么这对您来说可能是一个不错的选择.这种方式的使用HAVING是MySQL扩展(不是标准的),但是再次,CONCAT所以我们已经进入MySQL特定的东西了.:-)但是,再次,仔细检查你的现实生活环境.
如果您还没有索引,那么创建索引,如果远程可能,我会使用选项2; 否则,选项1除非你能找到(或者Andy可以提供)HAVING没有建立大量中间结果集的东西的参考(如果非标准的话,它会非常酷,如果没有的话).无论如何,请EXPLAIN在您的特定环境中进行检查和测试.