4

现在我设置了一个数据库,如下例所示:

id (int(11)) | name (varchar(20)) | food (varchar(20)) | fastfood (varchar(3)) | pricerange (int(11))

1            | McDonalds          | American           | Yes                   | 1
2            | Outback            | BBQ                | No                    | 2
3            | Mortons            | Steakhouse         | No                    | 3

现在我设置了一个用户表单,如下所示:

<form action="index.php" method="GET" id="sheet">

    <select name="name1" id="name1">
        <option value="%">No Preference</option>
        <option value="outback">Outback</option>
        <option value="mcdonalds">McDonalds</option>
        <option value="mortons">Mortons</option>
    </select>

    <select name="food1" id="food1">
        <option value="%">No Preference</option>
        <option value="american">American</option>
        <option value="bbq">BBQ</option>
        <option value="steakhouse">Steakhouse</option>
    </select>

    <select name="fast" id="fast">
        <option value="%">No Preference</option>
        <option value="yes">Yes</option>
        <option value="no">No</option>
    </select>

    <select name="price" id="price">
        <option value="%">No Preference</option>
        <option value="1">Cheap</option>
        <option value="2">Middle Ground</option>
        <option value="3">Expensive</option>
    </select>

    <input type="submit" value="Submit" id="submit"></input>
    <input type="clear" value="Clear" id="Clear"<input>

</form>

现在,当我运行以下查询时,如果不是所有字段都匹配,我将不会得到任何结果。int当涉及到s & s时,如何操纵查询以显示基于最佳匹配的结果varchar

$query = "SELECT * FROM .$usertable 
             WHERE $name LIKE '$name' AND 
                   $food LIKE '$food1' AND 
                   $fastfood LIKE '$fast' AND 
                   $pricerange LIKE '$price' ";

全文搜索不起作用,因为 INT 和“OR”不会显示基于最佳匹配的结果。假设用户选择了 4 个选项中的 3 个,例如:BBQ | Yes | 2

现在,在这种情况下,最好的匹配是Outback,但是因为它也在尝试匹配快餐,所以它不会返回任何结果。如果有更多选择,它会变得更加复杂。

如果有人能对这个问题的解决方案有所了解,我将非常感激。

4

4 回答 4

3

首先,您需要解析这些整数。这些功能可以帮助您:

http://php.net/manual/en/function.intval.php

http://es.php.net/manual/en/function.trim.php

其次,您可以操纵您的查询,以便整数像$pricerange <= $price order by $pricerange desc

(此查询将首先为您提供价格范围较近的项目,从下方开始。您可以将其与另一个价格范围最接近的项目链接,从顶部开始,左连接或放置一个选择器从范围的上方或后方进行选择,以防它不是匹配。这只是一个半途而废的解决方案,但它有效,许多搜索算法实现了类似的东西。如果你挤压你的大脑,你可能会找到更接近你想要的东西,用JOIN, UNION,等链接查询。查看mysqlLIMIT上的这些条目手册

第三,您也可以使用JOIN..ON NOT NULL为您的搜索添加条件。看看这个(如果你不知道如何使用 join,这个

最后,我建议您熟悉PDO。这是在 PHP 中执行正确的数据库查询的最佳方式。

于 2012-07-18T21:14:05.933 回答
2

这实际上不是查询语法的问题。这里的问题是为您的应用程序定义您认为是“最佳匹配”的内容。像这样的函数没有直接的最佳匹配:您需要自己定义它。一旦你这样做了,你就可以着手实施它。

作为一个简单的示例,您可以将“最佳匹配”定义为其中尽可能多的显式查询参数匹配,并且 int 值参数尽可能接近。然后你可以为每场比赛计算一个“分数”,并按此排序。

所以假设搜索是food=BBQ, fastfood=Yes, price=2. 您的查询可能如下所示:

SELECT *,
    SUM(
        food=:food, -- if food matches, add one to score
        fastfood=:fastfood, -- if fastfood matches, add one to score
        -- finally, add 2 for an exact price match, 1 for off-by-one price match,
        -- 0 for off-by-two matches, etc
        (SELECT MAX(price)-1 from foods)-ABS(price-:price) 
    ) AS score
    FROM foods ORDER BY score DESC

您可以通过调整分数的多少来调整您希望每场比赛的重要性。此外,您可以决定类别之间是否存在不同的“距离”。例如,也许“Steakhouse”比“American”更像“BBQ”,所以 Steakhouse 的分数应该更高。

这是一种简单的方法,但它可能效率低下,因为您需要为每一行计算一个分数。您可以通过多个查询加快速度:首先查找完全匹配;如果没有找到,请计算所有部分匹配的行的分数。仅当仍未找到任何内容时才回退到总表搜索。

SELECT * FROM foods WHERE food=:food AND fastfood=:fastfood AND price=:price;
-- if no matches then:
SELECT *, SUM(food=:food, fastfood=:fastfood, (SELECT MAX(price)-1 from foods)-ABS(price-:price)) AS score
WHERE food=:food OR fastfood=:fastfood OR price=:price ORDER BY score DESC
于 2012-07-18T21:34:56.030 回答
1

如果您在 MySQL 上查看并尝试“匹配”指令!并使用“OR”而不是“AND”!(比赛是我认为最好的方式)

于 2012-07-18T21:01:37.660 回答
1

嗯,MySQL 数据库在设计时并没有考虑到这种情况。它应该实际返回您的要求,而不是为您进行猜测。

不幸的是,这意味着您需要在代码中实现此逻辑。搜索完全匹配,然后如果这不起作用,则搜索某些项目匹配的情况。

作为设计师,比赛的相关性将取决于您。

这并不是说您不能组合一个复杂的查询来获取您想要的数据,您只需要构建该逻辑(也许通过对各种 SELECT 语句的结果执行 UNIONS)。

于 2012-07-18T21:03:29.970 回答