所以我有三个表,一个是posts
,有id,title,content,timestamp
列。其他为tags
,列id,tag
,第三posttags
描述posts
和tags
之间的一对多关系,列postid,tagid
。
现在,不要在表hidden,featured
中使用posts
等列来描述帖子应该对所有人可见还是应该显示在特殊的精选页面上,我想为什么不用标签来节省时间。所以我决定所有标记为#featured
的帖子都会被展示,所有标记为#hidden
的帖子都会被隐藏。
实现第一个很简单,因为我可以使用连接查询,在我的where子句中我可以提到WHERE tag='featured'
,这将获得我的所有精选帖子。
但如果我要使用查询,请举例说明标记为#sports
和#hidden
的帖子
SELECT * FROM posts
INNER JOIN posttags ON posttags.postid = posts.id
INNER JOIN tags ON posttags.tagid = tags.id
WHERE tag !='hidden'
但是仍然会返回标记为hidden
的帖子,因为它还标记了sports
PS 我的问题与此问题不同:Select a post that does not have a particular tag因为它直接使用tagid而我无法使用double join来检查标记名称而不是tagid。而且我希望在相同的查询中检索帖子的其他标签,这在该问题的答案中使用该方法是不可能的
答案 0 :(得分:4)
通过发布对标记进行分组,然后使用HAVING
子句过滤那些不包含'hidden'
标记的组。由于MySQL的隐式类型转换和缺乏真正的布尔类型,可以做到:
SELECT posts.*
FROM posts
JOIN posttags ON posttags.postid = posts.id
JOIN tags ON posttags.tagid = tags.id
GROUP BY posts.id
HAVING NOT SUM(tag='hidden')
答案 1 :(得分:1)
您可以使用NOT EXISTS
子查询执行此操作:
SELECT p.*, t.* -- what columns you need
FROM posts AS p
INNER JOIN posttags AS pt
ON pt.postid = p.id
INNER JOIN tags AS t
ON pt.tagid = t.id
WHERE NOT EXISTS
( SELECT *
FROM posttags AS pt_no
INNER JOIN tags AS t_no
ON pt_no.tagid = t_no.id
WHERE t_no.tag = 'hidden'
AND pt_no.postid = p.id
) ;
或等效的LEFT JOIN / IS NULL
:
SELECT p.*, t.*
FROM posts AS p
LEFT JOIN posttags AS pt_no
INNER JOIN tags AS t_no
ON t_no.tag = 'hidden'
AND pt_no.tagid = t_no.id
ON pt_no.postid = p.id
INNER JOIN posttags AS pt
ON pt.postid = p.id
INNER JOIN tags AS t
ON pt.tagid = t.id
WHERE pt_no.postid IS NULL ;
Thsi类型的查询称为反半连接或仅反连接。在你的情况下,它稍微复杂一些,因为条件(tag='hidden'
)在第3个表中。