我有三个表:posts,tags和posts_has_tags(这有利于帖子和标签之间的多对多关系)。帖子可以包含任意数量的标签。
'posts'表格包含以下列: idposts 文本
'tags'表包含以下内容: idtags 名称
至于'posts_has_tags'表: posts_idposts tags_idtags
我不能做的是提出一个查询来选择所有帖子,除了那些在分配给它们的“名称”列中具有特定值的标签(或标签)的帖子。它似乎应该包含一个“NOT EXISTS”,但我无法完全包围它。
提前感谢您的帮助。
编辑:
另外,是否可以同时将结果集限制为某些标签?例如:
排除标签:a,b 包含的标签:c
使用标签'a'发布,'f'不会将其转换为结果集(因为如果包含标签,则不会)。 带有标签'a','b','c'的帖子也不会进入结果集(因为它的'a'和'b'是排除的标签)。 带有标签'c'的帖子,'f'会将其设为结果集,因为'c'是包含的标签。
最终编辑 我终于找到了一个似乎有效且性能相当好的解决方案:http://www.mysqldiary.com/a-many-to-many-relationship-table-solving-the-exclude-relation-problem/
答案 0 :(得分:4)
您可以使用反加入。
SELECT p.*
FROM posts p
LEFT JOIN post_has_tags pt ON (pt.post_id = p.id)
LEFT JOIN tags t ON (t.id = pt.tag_id AND t.name IN ('test','test1','test2'))
WHERE t.id IS NULL
GROUP BY p.id
如果要强制包含其他标记,则执行另一个连接。
SELECT p.*
FROM posts p
LEFT JOIN post_has_tags pt ON (pt.post_id = p.id)
LEFT JOIN tags t ON (t.id = pt.tag_id AND t.name IN ('a','b'))
INNER JOIN tags t2 ON (t2.id <> t.id AND t2.id = pt.tag_id AND t2.name IN ('c'))
WHERE t.id IS NULL
GROUP BY p.id
这将优先考虑排除而不是包含 如果要优先考虑包含,请将内部联接替换为:
INNER JOIN tags t2 ON (t2.id = pt.tag_id AND t2.name IN ('c'))
答案 1 :(得分:3)
SELECT p.*
FROM posts AS p
WHERE NOT EXISTS
( SELECT *
FROM posts_has_tags AS pt
JOIN tags AS t
ON pt.tags_idtags = t.idtags
WHERE pt.posts_idposts = p.idposts
AND t.name = @CertainForbiddenTagName
)
如果您要禁止许多标记名称,请改用:
AND t.name IN (List of ForbiddenTagNames)
对于您更新的第二个问题,只需添加类似的EXISTS
:
AND EXISTS
( SELECT *
...
)
答案 2 :(得分:0)
select * from posts where idposts in
(select posts_has_tags.posts_idposts from posts_has_tags
join tags on tags.idtags = posts_has_tags.tags_idtags
where tags.name not in ('value1','value2',...))
答案 3 :(得分:0)
我终于找到了一个似乎有效并且表现相当出色的解决方案:http://www.mysqldiary.com/a-many-to-many-relationship-table-solving-the-exclude-relation-problem/