1

我有一个客户想让我做一个标签系统。我有三个表:itemstagsitem_tag_assoc- 最后一个仅用于关联 item_ids 和 tag_ids。这是我遇到的问题:

如果用户请求包含标签 [1, 2, 3] 和排除标签 [4, 5, 6],则结果应该是在 [1, 2, 3] 中具有每个标签(不仅仅是一个)且没有标签的所有项目在 [4, 5, 6] 中。如何编写查询来完成此操作?

我进行了足够的研究以找出标签包含的内部连接:

SELECT i.item_id, i.item_title FROM items AS i INNER JOIN tag_item_assoc AS tia1 ON (tia1.item_id = i.item_id AND tia1.tag_id = 1)

...并且只需在相同的内部连接模式上链接您想要包含的尽可能多的标签。它可能有点笨重,但用户在继续之前不会选择超过 4 或 5 个标签,所以它会做。

我真的希望我能以同样的方式排除,并将所有内容包装到一个查询中:

INNER JOIN tag_item_assoc AS tia2 ON (tia2.item_id = i.item_id AND tia2.tag_id!= 2)

但很快就变得很明显,这是行不通的。我读了几篇文章说LEFT OUTER JOINs 可以让我在包含时排除,但我无法弄清楚,主要是因为杂散WHERE子句。LEFT OUTER JOIN我尝试的s 和s 的任何排列INNER JOIN要么产生错误,要么产生非常混乱的结果。

说了这么多——这里有人知道我怎么能做到这一点吗?我很抱歉没有提供任何有用的代码示例。如果 s 是一个障碍,我可以从头开始INNER JOIN- 我只需要一种方法来同时完成多个关联包含和排除。提前感谢您的帮助和专业知识!

4

3 回答 3

0

您需要将记录实例的数量与标签的数量相匹配:

SELECT a.item_id -- , add other columns here
FROM   items a
          INNER JOIN item_tag_assoc b
             ON a.item_id = b.item_id
WHERE b.tag_id IN (1, 2, 3) AND
      b.tag_id NOT IN (4, 5, 6)
GROUP BY a.item_id
HAVING COUNT(a.item_id) = 3
于 2012-08-13T07:49:56.090 回答
0
SELECT a.*
FROM items a
     INNER JOIN item_tag_assoc b
         ON a.item_id = b.item_id
     INNER JOIN tags c
         ON a.tag_id = c.tag_id
WHERE c.tag_id IN(1) AND
      c.tag_id IN(2) AND
      c.tag_id IN(3) AND
      c.tag_id NOT IN (4) AND
      c.tag_id NOT IN (5) AND
      c.tag_id NOT IN (6) ;
于 2012-08-13T07:52:06.307 回答
0

找到了答案。而不是像这样添加INNER JOINs :

INNER JOIN tag_item_assoc AS tia2 ON (tia2.item_id = i.item_id AND tia2.tag_id!= 2)

我添加了一个带有单个内部连接的子查询:

WHERE i.item_id NOT IN ( SELECT i.item_id FROM items AS s INNER JOIN tag_item_assoc AS tia1 ON (tia1.item_id = i.item_id AND tia1.tag_id IN (4, 5, 6)))

子查询创建一组item具有 [4, 5, 6] 中任何标签的所有 s,并WHERE i.iten_id NOT IN消除与该组匹配的任何记录。

感谢大家的努力!希望这会帮助别人。

于 2012-08-13T18:20:41.380 回答