繁体   English   中英

具有多个字段的多个关键字的Php MySql查询

[英]Php MySql Query with Multiple Keyword for Multiple Fields

我正在使用php和mySql创建一个Web应用程序。

它基本上是一个带有单个文本框的简单搜索表单。

用户输入可以是关键字的组合,我在string_ireplace()之后使用php explode()函数。

现在我想在一个表中搜索每个关键字(比如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>";
    }

?>

我得到的输出如下:

完全匹配所有值

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';
?>

这应该创建一个这样的查询:

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

我刚才了解了CASE WHEN ,从这个答案来看几乎是一个相同的问题。 我设置的方式是,如果field1在关键字中,则应返回1,如果field2在关键字中,则返回1,依此类推。 这会给你rank ,一个你可以排序的新领域。 最初的回答者说它不是很有效,所以你可能想要查看该页面上的其他解决方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM