我有一个客户要我制作标签系统。我有三个表:items
,tags
和item_tag_assoc
- 最后一个表只用于关联item_ids和tag_ids。这是我遇到的问题:
如果用户请求包含标签[1,2,3]和排除标签[4,5,6],则结果应该是[1,2]中包含 EVERY 标签的所有项目3 [5,5]中的(不仅仅是一个)和 NO 标签。如何编写查询来完成此任务?
我研究得足以找出标签包含的内连接:
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 JOIN
可以让我在我加入时排除,但我无法弄明白,主要是因为流浪WHERE
条款。我试过的LEFT OUTER JOIN
和INNER JOIN
的任何排列都会产生错误或非常令人困惑的结果。
所有这一切 - 这里的任何人都知道如何实现这一目标吗?我为没有提供任何有用的代码示例而道歉。如果INNER JOIN
是一个障碍,我可以从头开始 - 我只需要一种方法同时完成多个关联包含和排除。提前感谢您的帮助和专业知识!
答案 0 :(得分: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
答案 1 :(得分: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) ;
答案 2 :(得分:0)
找到答案。而不是像这样添加INNER JOIN
:
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]和WHERE i.iten_id NOT IN
中的任何标记,可以消除与该集合匹配的任何记录。
感谢大家的努力!希望这会有所帮助。