考虑具有POSTS和TAGS的博客的典型场景。
我需要找到TAGS给定列表中没有TAGS的所有POSTS。
这意味着选择了没有列出任何标签的帖子。或者,相反地说,不会选择列表中包含任何标签的帖子。
如何构建合适的查询来执行此操作?
出于本示例的目的,查询应该与SQLITE3数据库一起使用,该数据库具有POSTS表,TAGS表和POSTS_TAGS表,以便查询
select p.title, t.name from posts p
inner join posts_tags pt on pt.post_id = p.id
inner join tags t on t.id = pt.tag_id
返回所有加入其代码的帖子(多次列出多个代码的帖子)。
我认为答案在于获取帖子的所有标签,所以我尝试使用group_concat
将每个帖子的所有标签减少到一行,但无法使其正常工作。这是我试过的:
select p.title, t.name, group_concat(t.name) from posts p
inner join posts_tags pt on pt.post_id = p.id
inner join tags t on t.id = pt.tag_id;
但是这会返回一行作为所有帖子的所有标签的最后一个帖子。下一步是排除标记包含任何被排除的行的行。
我会继续尝试解决这个问题,但如果有人能够提出一个查询来返回所有没有任何特定TAGS的帖子,那么这将非常有帮助。
答案 0 :(得分:1)
您可以使用correlated subquery查找帖子的所有标签,然后使用NOT EXISTS检查是否找不到标签:
SELECT *
FROM posts
WHERE NOT EXISTS (SELECT 1
FROM posts_tags
WHERE posts_tags.post_id = posts.id
AND posts_tags.tag_id IN (1, 22, 333, ...))
还可以使用outer join并检查连接与任何标记记录不匹配的位置:
SELECT posts.*
FROM posts
LEFT JOIN posts_tags ON posts.id = posts_tags.post_id
AND posts_tags.tag_id IN (1, 22, 333, ...)
WHERE posts_tags.tag_id IS NULL
...但这并不是那么有效,因为它需要数据库在过滤掉之前构造所有已连接的记录。