【问题标题】:Mysql Join Query gives the same results multiple timesMysql Join Query 多次给出相同的结果
【发布时间】:2010-02-23 01:01:24
【问题描述】:

我有两张桌子。一个是items,一个是tags。查询的here

这个想法是创建一个搜索框来搜索项目,然后通过选择标签来缩小搜索范围。 (某种分面搜索)。

在摆弄了 mysql 教程之后,我想出了这个:

SELECT `items`.`id`, `items`.`name`, `items`.`pay`, `items`.`desc`
FROM `items`LEFT JOIN (`tags`) ON (`tags`.`item_id`=`items`.`id`) 
WHERE (
    (`tags`.`type`='food' AND `tags`.`name`='pizza')
    OR (`tags`.`type`='drinks' AND `tags`.`name`='lemonade')
    --And so on for every tag
)
ORDER BY `pay` DESC LIMIT 0 , 30

(我删除了查询中的全文搜索,因为它现在不相关)

效果很好,但我有两个问题:

  1. 如果用户没有选择任何标签,每个附加了超过 1 个标签的项目都会显示超过 1 次
  2. 如果用户选择两个标签,例如 food=>pizza 和 Drinks=>lemonade,每个带有比萨饼或柠檬水或两者的商品都会显示,我只想要同时附有这两个标签的商品。李>

是否有可能用不同的mysql查询来解决这些问题?或者我应该在 php 代码中解决这些问题。 (或者我这样做完全错了,有没有更好的方法来使用标签?)

希望我说清楚了。

格,

基础

【问题讨论】:

    标签: php mysql


    【解决方案1】:

    在SELECT后面加上关键字DISTINCT?

    SELECT DISTINCT `items`.`id`, `items`.`name`, `items`.`pay`, `items`.`desc` 
    FROM `items`LEFT JOIN (`tags`) ON (`tags`.`item_id`=`items`.`id`)  
    WHERE ( 
        (`tags`.`type`='food' AND `tags`.`name`='pizza') 
        OR (`tags`.`type`='drinks' AND `tags`.`name`='lemonade') 
        --And so on for every tag 
    ) 
    ORDER BY `pay` DESC LIMIT 0 , 30 
    

    至于你的第二个问题......你的逻辑是错误的。如果我理解正确,您希望按 items.id 分组,然后拒绝返回的行数与所选标签数不同的项目......也许是这样的:

    SELECT DISTINCT `items`.`id`, `items`.`name`, `items`.`pay`, `items`.`desc` 
        FROM `items`LEFT JOIN (`tags`) ON (`tags`.`item_id`=`items`.`id`)  
        WHERE ( 
            (`tags`.`type`='food' AND `tags`.`name`='pizza') 
            OR (`tags`.`type`='drinks' AND `tags`.`name`='lemonade') 
            --And so on for every tag 
        ) 
        GROUP BY `items`.`id` 
        HAVING COUNT(*) = 2 
        ORDER BY `pay` DESC LIMIT 0 , 30 
    

    ... 并将 HAVING COUNT(*) = 2 中的 2 替换为您尝试同时匹配的标签数...

    【讨论】:

    • 这是一个很难回答的问题...就性能而言,只要您设置适当的索引就应该没问题...我的观点是,如果它始终如一地正常工作并且是对你的应用来说“足够快”,去吧。
    【解决方案2】:

    试试 WHERE tag.id IN (SUBQUERY)

    SELECT `items`.`id`, `items`.`name`, `items`.`pay`, `items`.`desc`
    FROM `items`  WHERE items.id IN (SELECT DISTINCT item_id
       FROM tags
       WHERE (
        (`tags`.`type`='food' AND `tags`.`name`='pizza')
        OR (`tags`.`type`='drinks' AND `tags`.`name`='lemonade'))
        --And so on for every tag
    )
    ORDER BY `pay` DESC LIMIT 0 , 30
    

    【讨论】:

    • 这解决了克隆结果的问题,但是当用户选择超过 1 个标签时,它不会返回具有两个标签的项目。相反,它只返回带有所选标签之一的每个项目。有什么想法吗?
    • 如果您只想要披萨和柠檬水的项目,只需将您的 OR 更改为 AND。这也适用于vicatcu的方法,如果你想要它们,不需要计算有多少标签。
    • 那行不通。每个标签/类型组合都有自己的行。所以 SELECT DISTINCT item_id FROM tags WHERE ( (tags.type='food' AND tags.name='pizza') AND (tags.type='drinks' AND tags .name='lemonade')) 根本不会返回任何结果,因为一行不能包含类型和名称的两个值。
    猜你喜欢
    • 2011-10-20
    • 1970-01-01
    • 1970-01-01
    • 2020-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-19
    相关资源
    最近更新 更多