我正在使用php和mySql创建一个Web应用程序.
它基本上是一个带有单个文本框的简单搜索表单.
用户输入可以是关键字的组合,我explode()
之后使用php 函数string_ireplace()
.
现在我想在一个表中搜索每个关键字(比如val 1,val 2,..... val n)对每个字段(比如提交1,提交2,......字段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>";
}
?>
Run Code Online (Sandbox Code Playgroud)
我得到的输出如下:
完全匹配所有值
SELECT*FROM TABLE WHERE(filed1 ='val1'或filed2 ='val1'或filed3 ='val1'或filed4 ='val1')AND(filed1 ='val2'或filed2 ='val2'或filed3 ='val2'OR filed4 ='val2')AND(filed1 ='val3'或者filed2 ='val3'或者filed3 ='val3'或者filed4 ='val3')
匹配所有值PARTIALLY
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%')
匹配val1和val2
SELECT*FROM TABLE WHERE(filed1 ='%val1%'OR filed2 ='%val1%'OR filed3 ='%val1%'OR filed4 ='%val1%')AND(filed1 ='%val2%'OR filed2 = '%val2%'或已提交3 ='%val2%'或已提交4 ='%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).我希望我能够解释我到底要找什么.
这是一个答案,它处理可伸缩性问题(限制用户可以搜索的关键字数量)和按相关性排序(每个地图匹配关键字的数量).我删除了检查空值的内容,但我添加了一些内容; 阅读评论看看是什么.没有测试过,所以我不知道它的表现如何......
<?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';
?>
Run Code Online (Sandbox Code Playgroud)
这应该创建一个这样的查询:
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
Run Code Online (Sandbox Code Playgroud)
我刚才CASE WHEN
从这个答案中了解到了一个几乎完全相同的问题.我设置它的方式,如果field1
在关键字中,则应返回1,如果在关键字中则添加1 field2
,依此类推.这为您提供rank
了一个可以排序的新字段.最初的回答者说它不是很有效,所以你可能想要查看该页面上的其他解决方案.
归档时间: |
|
查看次数: |
5366 次 |
最近记录: |