我正在使用 php 和 mySql 创建一个网络应用程序。
它基本上是一个带有单个文本框的简单搜索表单。
用户输入可以是关键字的组合,为此我在 string_ireplace()
之后使用了 php explode()
函数。
现在我想针对单个表中的每个字段(比如 filed 1、filed 2、......字段 n)搜索每个关键字(比如 val 1、val 2、..... val n) .
我觉得我将不得不使用多个 for 循环 - 为每个值搜索所有字段。
但是我怎样才能根据相关性对结果进行排序,即。匹配所有值的记录将首先出现,依此类推。
由于此表排序不是在数据库级别进行的,因此我无法使用 ORDER BY
子句。
编辑:好的。我想我必须详细解释我正在寻找什么以及我已经取得了什么。以下是我写的代码,它几乎达到了我的目的,但看起来很耗时(执行)。
<?php
//$str = mysql_real_escape_string($_GET['searchText']);
$str = "val1, val2, val3";
$str = trim($str);
// check for an empty string and display a message.
if ($str == "") {
$resultmsg = "<p>Search Error: Please enter a search keyword...</p>" ;
}
$str = explode(",",$str);
//Create array for all fields
$fields = array("filed1","filed2","filed3","filed4");
$condition = "";
for ($j=0;$j<count($str);$j++){
for ($i=0;$i<count($fields);$i++){
$condition = $condition.$fields[$i]." = '".$str[$j]."' OR ";
}
$condition = rtrim($condition, " OR");
$condition = $condition.") AND (";
}
$condition = rtrim($condition, " AND (");
$sql = "SELECT * FROM TABLE WHERE (".$condition;
echo $sql;
echo "<br /><hr>";
$condition = "";
for ($j=0;$j<count($str);$j++){
for ($i=0;$i<count($fields);$i++){
$condition = $condition.$fields[$i]." = '%".$str[$j]."%' OR ";
}
$condition = rtrim($condition, " OR");
$condition = $condition.") AND (";
}
$condition = rtrim($condition, " AND (");
//$condition = str_replace("="," LIKE ",$condition);
$sql= "SELECT * FROM TABLE WHERE (".$condition;
echo $sql;
echo "<br /><hr>";
//testing
if (count($str)==3){
$condition = "";
for ($j=0;$j<count($str)-1;$j++){
for ($i=0;$i<count($fields);$i++){
$condition = $condition.$fields[$i]." = '%".$str[$j]."%' OR ";
}
$condition = rtrim($condition, " OR");
$condition = $condition.") AND (";
}
$condition = rtrim($condition, " AND (");
//$condition = str_replace("="," LIKE ",$condition);
$sql= "SELECT * FROM TABLE WHERE (".$condition;
echo "<strong>Matching ".$str[0]." AND ".$str[1]."<br /></strong>";
echo $sql;
echo "<br /><hr>";
$condition = "";
for ($j=1;$j<count($str);$j++){
for ($i=0;$i<count($fields);$i++){
$condition = $condition.$fields[$i]." = '%".$str[$j]."%' OR ";
}
$condition = rtrim($condition, " OR");
$condition = $condition.") AND (";
}
$condition = rtrim($condition, " AND (");
//$condition = str_replace("="," LIKE ",$condition);
$sql= "SELECT * FROM TABLE WHERE (".$condition;
echo "<strong>Matching ".$str[1]." AND ".$str[2]."<br /></strong>";
echo $sql;
echo "<br /><hr>";
$condition = "";
for ($j=0;$j<count($str);$j=$j+2){
for ($i=0;$i<count($fields);$i++){
$condition = $condition.$fields[$i]." = '%".$str[$j]."%' OR ";
}
$condition = rtrim($condition, " OR");
$condition = $condition.") AND (";
}
$condition = rtrim($condition, " AND (");
//$condition = str_replace("="," LIKE ",$condition);
$sql= "SELECT * FROM TABLE> WHERE (".$condition;
echo "<strong>Matching ".$str[2]." AND ".$str[0]."<br /></strong>";
echo $sql;
echo "<br /><hr>";
}
?>
我得到的输出如下:
完全匹配所有值
SELECT * FROM TABLE WHERE (filed1 = 'val1' OR filed2 = 'val1' OR filed3 = 'val1' OR filed4 = 'val1') AND (filed1 = 'val2' OR filed2 = 'val2' OR filed3 = ' val2' OR filed4 = 'val2') AND (filed1 = 'val3' OR filed2 = 'val3' OR filed3 = 'val3' OR filed4 = 'val3')
部分匹配所有值
SELECT * FROM TABLE WHERE (filed1 = '%val1%' OR filed2 = '%val1%' OR filed3 = '%val1%' OR filed4 = '%val1%') AND (filed1 = '%val2%' OR filed2 = '% val2%' OR filed3 = '% val2%' OR filed4 = '% val2%') AND (filed1 = '% val3%' OR filed2 = '% val3%' OR filed3 = '% val3%'或 filed4 = '% val3%')
匹配 val1 和 val2
SELECT * FROM TABLE WHERE (filed1 = '%val1%' OR filed2 = '%val1%' OR filed3 = '%val1%' OR filed4 = '%val1%') AND (filed1 = '%val2%' OR filed2 = '% val2%' OR filed3 = '% val2%' OR filed4 = '% val2%')
匹配 val2 和 val3
SELECT * FROM TABLE WHERE (filed1 = '% val2%' OR filed2 = '% val2%' OR filed3 = '% val2%' OR filed4 = '% val2%') AND (filed1 = '% val3%' OR filed2 = '% val3%' OR filed3 = '% val3%' OR filed4 = '% val3%')
匹配 val3 和 val1
SELECT * FROM TABLE WHERE (filed1 = '%val1%' OR filed2 = '%val1%' OR filed3 = '%val1%' OR filed4 = '%val1%') AND (filed1 = '%val3%' OR filed2 = '% val3%' OR filed3 = '% val3%' OR filed4 = '% val3%')
我现在可以继续将获取的数据附加到我的结果表中。但不知何故,我觉得这不是一个明智的解决方案。此外,我对搜索值的数量有限制(例如,此处为 3)。我希望我能够解释我到底在寻找什么。
最佳答案
这是一个答案,它处理可扩展性(限制用户可以搜索的关键字数量)和按相关性排序(每张 map 匹配关键字的数量)的问题。我删除了检查空值之类的东西,但我添加了一些东西;阅读评论,看看是什么。还没有测试过,所以我不知道它的性能如何......
<?php
$str = preg_split('/[\s,\+]+/', $str); // splits $str into individual words when
// it finds spaces, commas, and/or plus
// signs. This way, you won't have to
// force users to use plus signs
$fields = array('field1', 'field2', 'field3', 'field4');
foreach ($keywords as $i => $keyword) {
// escapes and quotes those keywords to prevent against injection attack
$keywords[$i] = '"' . mysql_real_escape_string($keyword) . '"';
}
// concatenates the keywords into one string that we can use as a set in
// MySQL's IN() clause
$keywords = implode(',', $keywords);
$fieldSearchQueries = array ();
foreach ($fields as $thisField) {
// here's the IN() clause, checking each field against the set of keywords
$fieldSearchqueries[] = 'CASE WHEN ' . $thisField . ' IN (' . $keywords . ')'
. ' THEN 1 ELSE 0 END';
}
$query = 'SELECT *, ' . implode(' + ' $fieldSearchQueries) . ' AS rank '
. 'FROM TABLE WHERE rank > 0 ORDER BY rank';
?>
这应该创建一个类似这样的查询:
SELECT *,
CASE WHEN field1 IN ('India', 'Rainfall', 'English') THEN 1 ELSE 0 END
+ CASE WHEN field2 IN ('India', 'Rainfall', 'English') THEN 1 ELSE 0 END
+ CASE WHEN field3 IN ('India', 'Rainfall', 'English') THEN 1 ELSE 0 END
+ CASE WHEN field4 IN ('India', 'Rainfall', 'English') THEN 1 ELSE 0 END
AS rank
FROM TABLE
WHERE rank > 0
ORDER BY rank
我今天刚从 this answer 了解到CASE WHEN
这是关于一个几乎相同的问题。按照我设置的方式,如果 field1
在关键字中,它应该返回 1,如果 field2
在关键字中,它应该返回 1,依此类推。这为您提供了 rank
,一个您可以作为排序依据的新字段。不过,最初的回答者说它不是很有效,因此您可能还想查看该页面上的其他解决方案。
关于具有多个字段的多个关键字的 Php MySql 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7802724/