Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
两个不同字段上的MySQL搜索查询_Mysql - Fatal编程技术网

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

两个不同字段上的MySQL搜索查询,mysql,Mysql,我需要使用LIKE函数搜索两个字段,并且应该按照相反的顺序匹配。我的表格使用InnoDB,它没有全文搜索功能 考虑以下情况: 我有一个名为first_name和last_name列的users表。在其上,有一行具有以下值: { first_name: 'Ludwig', last_name: 'van Beethoven', } 案例: 你能找到路德维希·范·贝多芬吗 你能找到贝多芬·路德维希吗 你能搜索路德维希吗 你能找到贝多芬吗 我尝试了这个SQL语句,但没有成功 SELE

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

考虑以下情况:

我有一个名为first_name和last_name列的users表。在其上,有一行具有以下值:

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

你能找到路德维希·范·贝多芬吗 你能找到贝多芬·路德维希吗 你能搜索路德维希吗 你能找到贝多芬吗 我尝试了这个SQL语句,但没有成功

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

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

 SELECT CONCAT(first_name, ' ', last_name) as fullname 
      FROM users 
     WHERE CONCAT(first_name, ' ', last_name) LIKE '%doe%';
不幸的是,只需创建一个列别名,而不是一个可以在其他地方使用的变量。

最主要的是 请确保在名和姓上有一个复合索引。否则,不管您如何处理,最终都很容易进行全表扫描。因此,如果您还没有,请创建一个:

CREATE INDEX users_firstandlast ON users(first_name, last_name);
语法选项 一旦该索引就位,您就有了一些选项:

选项1:如上所述,在WHERE子句中重复CONCAT,因为As不会创建可以在WHERE子句中使用的名称:

用于检查您的特定情况,但在我的测试中,它说它使用复合索引,即使您在WHERE子句中使用函数

选项2:在这种特殊情况下,您可以在WHERE子句中始终使用两个LIKE s:

同样,这可以使用复合索引,而不会在first_name和last_name列上使用单独的索引-如果不使用通配符,则会这样做,但根据解释[并且您的里程数可能不同,始终检查],在这种情况下,它与表扫描一起使用

在选项3中,安迪说你可以用拥有来实现这一点。我的建议是,它将首先构建结果集,然后在将结果发送给客户机之前在最后应用have,因此我对此持谨慎态度。但是,在我的快速测试中,EXPLAIN告诉我,如果你有我上面提到的复合索引,HAVING版本会进行索引搜索,而不是表扫描。如果你用真实数据进行的测试证明了这一点,那么这可能是一个不错的选择。以这种方式使用have是一个MySQL扩展,不是标准的,但是CONCAT也是,所以我们已经开始研究MySQL特定的东西了但是,再次检查一下你的真实生活环境

结论
如果你还没有创建索引,那么如果有可能的话,我会选择选项2;否则,选项1除非你能找到,或者Andy能为没有建立大规模临时结果集的东西提供参考,否则如果不是标准的,如果不是,那将是非常酷的。无论如何,请在您的特定环境中使用EXPLAIN进行检查和测试。

当您选中两列时,类似的内容将区分大小写。因此,这应该会找到结果,但不是最佳性能:

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

这使得MySQL能够在每一行上进行工作。

从以下用户中选择*:CONCATfirst_name',last_name(如“%Ludwig%”或CONCATlast_name',first_name(如“%Ludwig%”)


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

+1 for answer+原因我从现已删除的答案中取消了查询。-1函数不应在where子句中使用。列别名可以使用have引用,请参见我的答案。@Andy:我完全同意您应该避免在WHERE子句中使用具有其他选项的函数,但它们不会自动变差,如果函数可以在索引上计算,请参见我的答案了解我的意思。我不认为这里有帮助,我比较了执行计划;请看我的答案中的注释,但我会非常感兴趣的是您的任何参考资料,以了解为什么它可能会出现。当您在两列中添加类似的内容时,是否真的会区分大小写?你有这方面的参考资料吗?我不明白为什么你如何创建值会对它是否区分大小写有任何影响。更新:在文档中没有看到任何内容,只是尝试了一下。不,concat并没有使like操作符突然区分大小写,至少在我的MySQL 5.1中没有使用MyISAM或InnoDB表安装Windows和Ubuntu,而且它真的不应该是特定于存储的:这是我上次这么做时遇到的问题,也许现在已经解决了。当时我在博客上写过。在你的博客文章中,你没有说它是什么版本。2007年我想5.0,但是。。。我在MySQL bugs数据库中讨论了一会儿,但是有太多的结果,其中大多数是人们误解了like应该如何工作,但至少有一个是一个真正的bug——但在你发表文章前几年在v4.1.11中修复了。显然,排序规则设置也可能是一个问题,但我所看到的那些是总数的一小部分,没有一个是关于使用函数导致的,这真的很奇怪。目前,我正在使用这个SQL语句。从以下用户中选择CONCATfirst_名称“”、last_名称作为全名:CONCATfirst_名称“”、last_名称(如“%string%”和CONCATlast_名称“”,
第一个名称,如“%string%”;它适用于所有情况。是否有可能或需要创建一个相关性索引以将最接近的结果推到顶部,或者mysql隐式地这样做?
SELECT CONCAT(first_name, ' ', last_name) as fullname 
FROM users 
WHERE first_name LIKE '%doe%' or last_name LIKE '%doe%';
SELECT CONCAT(first_name, ' ', last_name) AS fullname FROM users 
WHERE LOWER(CONCAT(first_name, ' ', last_name)) LIKE LOWER('%doe%');