我有一个带有输入框的表单,用户可以在其中指定其名称,名称可以是两个或多个单词,例如John Smith
或John Michael Smith
。
我必须编写一个查询,返回包含所显示名称中所有单词的记录。因此查询将返回具有所有这些单词的名称的记录,但可能具有不同的顺序。
例如,如果搜索字符串为John Michael Smith
,则查询应该能够返回名称为Michael John Smith
,Michael Smith John
,John Smith Michael
或某些组合的记录这些话就在那里。可以看出,只返回仍然包含名称字段中所有单词的记录,但可能具有不同的顺序。但是,它应该返回不包含部分名称的结果,例如,John Michael
不应该返回,因为它没有Smith
。
我试过这样的查询:
SELECT id, name FROM users WHERE
name LIKE '%Michael%' &&
name LIKE '%Smith%' &&
name LIKE '%John%'
同样的问题发生在:
SELECT * FROM users WHERE MATCH (name)
AGAINST ('+Michael +Smith +John' IN BOOLEAN MODE);
两个查询都返回John Michael
而不是包含所有三个单词的记录:(
我无法弄清楚如何将查询写入需求,以便我拥有。请帮忙。
答案 0 :(得分:2)
使用fulltext index。这是最简单/最快捷的方法。否则,您将无法解析搜索字符串,转换
John Michael Smith
到
SELECT ... WHERE (name LIKE '%John%') OR (name LIKE '%Michael%') OR (name LIKE '%Smith%')
由于LIKE %..%
搜索无法使用索引,因此很快就会感到痛苦,并且执行起来很慢。
请注意,全文索引目前仅限于MyISAM表,因此如果您使用的是InnoDB,则必须使用变通办法(MyISAM格式的并行表可以保存带有触发器的可搜索数据,以保持两个副本同步)。显然,InnoDB的Fulltext在开发流程中是最终,但它还没有。
答案 1 :(得分:1)
如果将名称保存在“name”字段中,则sql查询应该是这样的
首先按空格分解字符串
$params = explode(' ', $input_name);
然后将此附加到您的查询中:
$i = 0;
$q= '';
foreach($params as $p){
$p = strtolower($p);
if($i > 0) $q.= " and ";
$q.= "LOWER(name) like '%$p%'";
$i++;
}
$query="select .... where ".$q;
需要较低的东西才能使其不区分大小写。
答案 2 :(得分:1)
无论您将哪个变量设置为此输入的值,您都希望使用explode: http://php.net/manual/en/function.explode.php
$names = explode(' ', $userinput);
以空格作为分隔符。这将为您提供一个包含3个不同元素的数组(或者有许多元素)。
$names[0] = "John";
$names[1] = "Michael"
$names[2] = "Smith";
现在你需要通过strtolower运行它们,这样就不会出现问题了。
http://us3.php.net/manual/en/function.strtolower.php
foreach ($names as $name)
{
$name = strtolower($name);
}
现在我们有了
$names[0] = "john";
$names[1] = "michael"
$names[2] = "smith";
接下来,您需要构建一个函数,以所有可能的顺序重新组合这些变量。但是因为您的阵列中可能包含1,2,3或4个元素,所以您不知道需要多少查询。所以你检查:
$numberofnames = count($names);
然后创建一个函数来构建不同的名称组合:
$namecombo = "";
function createNames($numberofnames)
{
for($i=0; $i <= $Numberofnames; $i++)
{
$namecombos[i] .= $names[i];
}
因此。这是一个不完整的答案,因为我们遇到了一个问题。你需要一个for循环来生成名称组合,但你还需要一个for循环来生成你需要多少个for循环。不是我能想到的一种编码方式。但是......希望这能让你更接近答案。
for($i=0; $i <= $Numberofnames; $i++)
{
$secondnamecombo[i] = $names[$i - 1]
etc...
}
}