我想选择包含特定标记的所有帖子。我正在尝试这个查询:
SELECT GROUP_CONCAT(t.tag_name) taglist
FROM posts p
JOIN posts_tags pt ON p.post_id = pt.post_id
JOIN tags t ON t.tag_id = pt.tag_id
WHERE (p.post_private = 0) AND t.tag_name = 'php'
GROUP BY p.post_id
问题是,上面的查询会选择包含php
标记的所有帖子,但不会选择帖子中可能包含的任何其他标记。如果没有AND t.tag_name = 'php'
部分,它会选择帖子中的每个标记,但我希望能够按标记进行过滤...
任何想法如何做到这一点?我尝试了很多东西,但无法弄明白......
没有AND
声明的示例数据:
|| *taglist* ||
|| php,echo ||
|| c++, cout ||
使用AND
语句的示例数据:
|| *taglist* ||
|| php ||
我想要的是什么:
|| *taglist* ||
|| php,echo ||
(仅包含PHP标记的帖子)
答案 0 :(得分:2)
SELECT p.post_id, GROUP_CONCAT(t.tag_name) taglist
FROM posts p
/* These 2 joins get the list of all tags */
INNER JOIN posts_tags pt
ON p.post_id = pt.post_id
INNER JOIN tags t
ON pt.tag_id = t.tag_id
/* These 2 joins guarantee the 'php' tag is included */
INNER JOIN posts_tags pt2
ON p.post_id = pt2.post_id
INNER JOIN tags t2
ON pt2.tag_id = t2.tag_id
AND t2.tag_name = 'php'
WHERE p.post_private = 0
GROUP BY p.post_id
答案 1 :(得分:1)
我会尝试解释为什么你的第一次尝试不起作用。
您真正要做的是找到所有一个标签的帖子都是'php'。
但是他们的标记会在多行中传播,因此t.tag_name = 'php'
无效,因为它会过滤掉所有没有'php'标记的行。
如果要检查依赖于多行的条件,
你要么创建一个子查询(找到所有有php标签的post_id)
p.post_id IN
( SELECT pt2.post_id
FROM post_tags pt2
JOIN tags t2
ON t2.tag_id = pt2.tag_id
WHERE t2.tag_name = 'php'
)
但仍然使用所有相关标签加入这些post_id。
SELECT GROUP_CONCAT(t.tag_name) taglist
FROM posts p
JOIN posts_tags pt
ON p.post_id = pt.post_id
JOIN tags t
ON t.tag_id = pt.tag_id
WHERE (p.post_private = 0)
AND p.post_id IN
( SELECT pt2.post_id
FROM post_tags pt2
JOIN tags t2
ON t2.tag_id = pt2.tag_id
WHERE t2.tag_name = 'php'
)
GROUP BY p.post_id
或者你更聪明地做到这一点,因为Stefanelli展示了另外2个JOIN(其行为类似于子查询)