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

标签 php mysql sql

我正在使用 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/

相关文章:

mysql - 首先求和,然后乘以该值

php - 注销脚本不起作用

mysql - 在 Laravel 中使用 DataTables 时出现无效参数编号错误

php artisanserve命令显示错误消息

c# - 在并行循环中使用 SMO 从 .net 中的 SQL Server 数据库编写对象定义脚本

sql - 使用 SQL 解析/查询 XML

php - 表 UI View : Mysql - Php

php - 使用 PHP 在动态创建表格中应用表格样式

PHP date_diff 函数返回错误结果

php - 除了使用 system() 函数进行备份之外,还需要一种运行 mysqldump 的方法