mysql根据另一个联接表的结果查询联接表
我有五张桌子。标签,流,流标签,帖子,帖子标签。streams_标记和posts_标记只是标记、streams和posts的联接表 我想从posts表中选择所有posts,这些posts表包含通过streams\u tags表与流关联的所有标记。例如,如果一个流有相关的标签cat,dog,那么所有带有相关标签cat,dog的帖子都应该返回。不管帖子中是否有更多的标签而不是猫,狗,只要它包含猫,狗标签就行 标签: id |名称 溪流: id |名称 streams\u标签: id |流|标记| id posts:id | name posts_标签:id | post_id | tag_id 此查询应返回指定的结果集:mysql根据另一个联接表的结果查询联接表,mysql,Mysql,我有五张桌子。标签,流,流标签,帖子,帖子标签。streams_标记和posts_标记只是标记、streams和posts的联接表 我想从posts表中选择所有posts,这些posts表包含通过streams\u tags表与流关联的所有标记。例如,如果一个流有相关的标签cat,dog,那么所有带有相关标签cat,dog的帖子都应该返回。不管帖子中是否有更多的标签而不是猫,狗,只要它包含猫,狗标签就行 标签: id |名称 溪流: id |名称 streams\u标签: id |流|标记| i
SELECT p.id
, p.name
FROM posts p
WHERE NOT EXISTS
( SELECT 1
FROM streams_tags st
WHERE st.stream_id = 201 /* <-- specified stream_id value */
AND NOT EXISTS
( SELECT 1
FROM posts_tags pt
WHERE pt.tag_id = st.tag_id
AND pt.post_id = p.id
)
)
当我们运行该查询来检查posts.id=67时,我们不会返回任何行。这意味着posts.id 67匹配指定流的所有标记
当我们再次运行它时,指定posts.id=68,我们将返回一行。我们返回的行是post_标记中缺少的streams_tag.tag_id值
因此,如果我们对每个post\u id运行这个查询,并检查这个查询是否返回行,我们就可以知道哪些post与指定的stream\u id的所有streams\u tags.tag\u id相匹配。。。为每个帖子id运行此查询
另一种完全不同的方法是获取帖子上匹配标记的数量,并将其与流上的标记数量进行比较
SELECT p.id
, p.name
, sc.st_count AS st_count
FROM ( SELECT stc.stream_id
, COUNT(DISTINCT stc.tag_id) AS st_count
FROM streams_tags stc
WHERE stc.stream_id = 201
GROUP BY stc.stream_id
) sc
CROSS
JOIN posts p
LEFT
JOIN posts_tags pt
ON pt.post_id = p.id
LEFT
JOIN streams_tags st
ON st.tag_id = pt.tag_id
AND st.stream_id = sc.stream_id
GROUP
BY p.id
, p.name
HAVING COUNT(DISTINCT st.tag_id) >= sc.st_count
注意:要从HAVING子句中可用的特定stream_id的streams_标记中获取标记计数,必须将其包括在查询的SELECT列表中。另一种方法是将该子查询下移到HAVING子句,然后在查询中重复指定的stream_id值两次
SELECT p.id
, p.name
FROM posts p
LEFT
JOIN posts_tags pt
ON pt.post_id = p.id
LEFT
JOIN streams_tags st
ON st.tag_id = pt.tag_id
AND st.stream_id = 201 /* <- specified stream_id */
GROUP
BY p.id
, p.name
HAVING COUNT(DISTINCT st.tag_id) >=
( SELECT COUNT(DISTINCT stc.tag_id) AS st_count
FROM streams_tags stc
WHERE stc.stream_id = 201 /* <- specified stream_id */
)
你试过什么?您需要使用内部联接来联接表。这就是你需要帮助的地方还是更微妙的地方?@Melanie-我已经尝试了太多东西,想在这里发布。我不相信我被困在连接上了。我被卡住的地方是能够确定一篇文章是否包含与流关联的所有标记。@Tony:欢迎来到Stackoverflow!这是一个棘手的问题,匹配所有标记,而不仅仅是任何标记。但是使用标准的MySQL语法是可以做到这一点的。哇,这非常好用。感谢您的详细解释和多种解决方案。我学到了很多。我真的很担心这件事,你帮我节省了很多时间和工作。这是我第一篇关于StackOverflow的帖子,现在我更喜欢它了。谢谢。@Tony:欢迎来到StackOverflow!仅供参考-这些查询在小集合上的性能将是合理的;但是,对于庞大的集合,即posts表中的数百万行,这两个查询可能会变成真正的资源消耗。POST_标记和streams_标记表上的适当覆盖索引对于最佳性能是必要的。
SELECT p.id
, p.name
FROM posts p
LEFT
JOIN posts_tags pt
ON pt.post_id = p.id
LEFT
JOIN streams_tags st
ON st.tag_id = pt.tag_id
AND st.stream_id = 201 /* <- specified stream_id */
GROUP
BY p.id
, p.name
HAVING COUNT(DISTINCT st.tag_id) >=
( SELECT COUNT(DISTINCT stc.tag_id) AS st_count
FROM streams_tags stc
WHERE stc.stream_id = 201 /* <- specified stream_id */
)