Mysql 选择没有特定标记的帖子
我有一个post/tag数据库,包含常用的post、tag和tag_post表。tag_post表包含tagid和postid字段 我需要查询帖子。当我想要获取具有特定标记的帖子时,我必须使用连接:Mysql 选择没有特定标记的帖子,mysql,sql,many-to-many,subquery,Mysql,Sql,Many To Many,Subquery,我有一个post/tag数据库,包含常用的post、tag和tag_post表。tag_post表包含tagid和postid字段 我需要查询帖子。当我想要获取具有特定标记的帖子时,我必须使用连接: ... INNER JOIN tag_post ON post.id = tag_post.postid WHERE tag_post.tagid = {required_tagid}` 当我想要获取包含tagIdA和tagIdB的帖子时,我必须使用两个连接(我最终有点接受了) 现在,我需要查询
... INNER JOIN tag_post ON post.id = tag_post.postid
WHERE tag_post.tagid = {required_tagid}`
当我想要获取包含tagIdA和tagIdB的帖子时,我必须使用两个连接(我最终有点接受了)
现在,我需要查询没有特定标签的帖子。我没多想就把=
改成了=代码>:
... INNER JOIN tag_post ON post.id = tag_post.postid
WHERE tag_post.tagid != {certain_tagid}`
轰!错误的逻辑
我确实想到了这个——只是把逻辑写在这里:
... INNER JOIN tag_post ON post.id = tag_post.postid
WHERE tag_post.postid NOT IN
(SELECT postid from tag_post where tagid = {certain_tagid})
我知道这会起作用,但由于我的成长方式,每当我用子查询编写查询时,我都会感到内疚(不管是否合理)
建议更好的方法吗?您可以将其视为“查找文章中标记中不匹配的所有行(针对特定标记)”
这是关于左连接的教科书用例
LEFT JOIN tag_post ON post.id = tag_post.postid AND tag_post.tagid = {required_tagid}
WHERE tag_post.tag_id IS NULL
注意,您必须在join的ON子句中具有标记id
有关联接类型的参考,请参见此处:您可以将其视为“查找文章中标记中不匹配的所有行(针对特定标记)”
这是关于左连接的教科书用例
LEFT JOIN tag_post ON post.id = tag_post.postid AND tag_post.tagid = {required_tagid}
WHERE tag_post.tag_id IS NULL
注意,您必须在join的ON子句中具有标记id
有关联接类型的参考,请参见此处:除了Gavin Toway的好答案之外,您还可以使用不存在的子查询:
where not exists
(
select *
from tag_post
where post.id = tag_post.postid
and tag_post.tagid = {required_tagid}
)
数据库通常以相同的方式执行这两个变量。我个人认为不存在
方法更容易阅读。除了加文·托维的好答案外,你还可以使用不存在
子查询:
where not exists
(
select *
from tag_post
where post.id = tag_post.postid
and tag_post.tagid = {required_tagid}
)
数据库通常以相同的方式执行这两个变量。我个人认为不存在
方法更容易阅读
当我想要获取包含tagIdA和tagIdB的帖子时,我必须使用两个连接(我最终有点接受了)
还有其他方法
通过仅对那些标签进行分组筛选,按标签分组,然后删除包含少于预期标签的任何组,可以获得所有同时标记了tagid
123和456的帖子的id
;然后可以使用结果过滤posts
表:
SELECT * FROM posts WHERE id IN (
SELECT postid
FROM tag_post
WHERE tagid IN (123,456)
GROUP BY postid
HAVING COUNT(*) = 2
)
如果一篇文章可以多次使用相同的tagid
标记,则需要将COUNT(*)
替换为性能较差的COUNT(不同的tagid)
现在,我需要查询没有特定标签的帖子
这称为反连接。最简单的方法是按照您的建议,将上面查询中的替换为而不是。我不会为此感到太内疚。另一种方法是使用外部联接,如中所建议
当我想要获取包含tagIdA和tagIdB的帖子时,我必须使用两个连接(我最终有点接受了)
还有其他方法
通过仅对那些标签进行分组筛选,按标签分组,然后删除包含少于预期标签的任何组,可以获得所有同时标记了tagid
123和456的帖子的id
;然后可以使用结果过滤posts
表:
SELECT * FROM posts WHERE id IN (
SELECT postid
FROM tag_post
WHERE tagid IN (123,456)
GROUP BY postid
HAVING COUNT(*) = 2
)
如果一篇文章可以多次使用相同的tagid
标记,则需要将COUNT(*)
替换为性能较差的COUNT(不同的tagid)
现在,我需要查询没有特定标签的帖子
这称为反连接。最简单的方法是按照您的建议,将上面查询中的替换为而不是。我不会为此感到太内疚。另一种方法是使用外部联接,如中所建议
@Quassnoi在MySQL中写了一篇关于反连接模式的文章,得出结论认为存在
的效率比备选方案低30%。@Quassnoi在MySQL中写了一篇关于反连接模式的文章,得出结论认为存在
的效率比备选方案低30%。很好。但是子查询的负罪感开始出现了。然而,我认为经过一定数量的and之后,这将比多个联接更有效。@merlinbeard:您也可以使用从子查询中具体化的表来形成联接(分别用于上述情况1和2的内部联接和外部联接);它产生了一个等效的执行计划,因此纯粹是一个表面上的改变。我发现这种方法更具可读性。正如您所说,当您搜索多个标记时,无子查询方法需要多次扫描(然后连接)tag\u post
,这几乎肯定效率较低。@eggyal--有一种更好的方法可以使用相同的连接:选择*FROM posts join tag\u post ON。。。其中,tagid在(123456)组中,通过postid具有SUM(tagid=123)和SUM(tagid=456)@gavintoway:Ooooh,我喜欢这样!)美好的但是子查询的负罪感开始出现了。然而,我认为经过一定数量的and之后,这将比多个联接更有效。@merlinbeard:您也可以使用从子查询中具体化的表来形成联接(分别用于上述情况1和2的内部联接和外部联接);它产生了一个等效的执行计划,因此纯粹是一个表面上的改变。我发现这种方法更具可读性。正如您所说,当您搜索多个标记时,无子查询方法需要多次扫描(然后连接)tag\u post
,这几乎肯定效率较低。@eggyal--有一种更好的方法可以使用相同的连接:选择*FROM posts join tag\u post ON。。。其中,tagid在(123456)组中,通过postid具有SUM(tagid=123)和SUM(tagid=456)@gavintoway:Ooooh,我喜欢这样!)谢谢-您的回复还明确了ON和WHERE子句之间的区别-可以在CHAN中使用