多字段多关键字Php MySql查询

多字段多关键字Php MySql查询,php,mysql,sql,Php,Mysql,Sql,我正在使用php和mySql创建一个web应用程序 它基本上是一个简单的搜索表单,只有一个文本框 用户输入可以是关键字的组合,我在string\u ireplace()之后使用phpexplode()函数 现在,我想针对单个表中的每个字段(例如字段1、字段2、…字段n)搜索每个关键字(例如val 1、val 2、…val n) 我觉得我将不得不使用多个for循环-对于每个值搜索所有字段 但我如何根据相关性对结果进行排序,即匹配所有值的记录将首先出现,以此类推 由于此表排序不在数据库级别,因此我无

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

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

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

现在,我想针对单个表中的每个字段(例如字段1、字段2、…字段n)搜索每个关键字(例如val 1、val 2、…val n)

我觉得我将不得不使用多个for循环-对于每个值搜索所有字段

但我如何根据相关性对结果进行排序,即匹配所有值的记录将首先出现,以此类推

由于此表排序不在数据库级别,因此我无法使用
orderby
子句

编辑:好的。我想我必须详细解释我在寻找什么,我已经取得了什么成就。我已经编写了以下代码,它几乎满足了我的目的,但看起来相当耗时(执行)


这里有一个答案,它涉及可伸缩性(限制用户可以搜索的关键字数量)和按相关性排序(每个地图匹配的关键字数量)的问题。我删除了检查空值之类的内容,但添加了一些内容;阅读评论,看看是什么。还没有测试过,所以我不知道它的性能如何

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

我今天刚刚了解了
案例,从中可以看出一个几乎相同的问题。按照我的设置方式,如果
field1
在关键字中,它应该返回1,如果
field2
在关键字中,则添加1,依此类推。这将为您提供
排名
,这是一个新字段,您可以按其排序。最初的回答者说这不是很有效,所以你可能还想查看该页面上的其他解决方案。

Hoo boy,这是个棘手的问题。我将此作为评论发布,因为它不是对您问题的直接回答,但您可能希望创建一个“搜索关键字”表。是的,所以您为了优化而复制数据。问题是:1。你是在做相似的搜索还是精确匹配?2.作为1的推论,每个字段中是只有一个关键字,还是由空格/标点符号分隔的单词集合?是的,我知道这很难。对于你的Q1,它是否准确或相似真的很重要。我将使用一个野生字符,并考虑两个作为1发生,对于Q2,我将指示用户使用+符号分开两个关键字,为了简单起见。我在想,如果我使用多个单独的查询(相当于关键字的数量),然后将结果合并到一个表中会怎么样。你脑子里有一些想法,你会问怎么做,到目前为止没有问题。但是,如果没有提供令人满意的信息和详细的会计规则,我相信给出的任何answear都将作为你自己的思维框架概念的基础,由于缺乏信息,将被限制在特定的路径上。@ArunavaDey我问这些问题的原因是,如果每个字段只包含一个关键字,那么你就不必使用LIKE,但如果它能容纳不止一个,你就会。使用大量查询然后用PHP编译结果肯定是最快的(在开发阶段),但不会得到很好的优化。最快的(服务器时间)是一个单独的搜索表。。。在解释搜索表的工作原理之前,我将等待更多信息。@Paul d'a在我的数据库中,每个字段只包含一个关键字。所以我觉得我不需要使用LIKE。对于只需在两个值中选择一个值的
CASE
语句,
IF()
更容易:
IF(field1 in(…),1,0)+IF(field2 in(…),1,0)+……
噢,太好了!谢谢你的信息。你知道它是否更有效吗?(老实说,我不知道在什么情况下,
是无效的;我只是从我链接到的答案中得到了这样的评论:-)这非常有效。但它也有一个缺点,例如,我用一个关键字“保险杠”搜索,我有一列项目,其中有“前保险杠”、“后保险杠”、“小保险杠”等项目。它应该返回这些结果,但显示0结果<代码>选择*,(当oem_零件号在(‘保险杠’)中时,案例1其他0结束+当品牌在(‘保险杠’)中时案例1其他0结束+当项目在(‘保险杠’)中时案例1其他0结束+当车辆在(‘保险杠’)中时案例1其他0结束+当制造在(‘保险杠’)时案例1其他0结束)如果您正在进行模糊搜索,则根据rank DESC排名>0的项目的排名
@kabir,这有点不同;原始问题/答案涉及精确的值对值匹配。当oem\u part\u不喜欢“%buffer%”时,您需要类似于
的情况,然后是1 ELSE 0 END
。如果你有多个搜索词,它会变得更复杂。@kabir这是真的,正如我在评论中提到的。听起来你需要一些更复杂的东西——当field1='buffer'时使用
CASE,然后当field1像'%buffer%'时使用2 ELSE 0 END+CASE,然后为你搜索的每个字段使用1 ELSE 0 END
?这使得精确匹配的排名比模糊匹配的排名高出一倍。然后为每个关键字复制这两个
CASE
s,然后为您搜索的每个字段复制整个内容。在这个阶段,查询变得相当冗长,但是您将得到一个相当好的相关性搜索。
<?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