需要sql查询帮助来查找标记有所有指定标签的内容

假设我有以下表格:

TAGS

id:整数
name:string

post

id:整数
主体

引用的Tagging

id:整数
tag_id:整数
post_id:整数

我将如何编写一个查询,选择所有标记有以下所有标记的post(标签表的名称属性):“Cheese”,“Wine”,“Paris”,“Frace”,“City”,“风景“,”艺术“

另请参阅: 需要有关sql查询的帮助以查找具有最多指定标记的内容 (注意:类似,但不重复!)

使用IN:

SELECT p.* FROM POSTS p WHERE p.id IN (SELECT tg.post_id FROM TAGGINGS tg JOIN TAGS t ON t.id = tg.tag_id WHERE t.name IN ('Cheese','Wine','Paris','Frace','City','Scenic','Art') GROUP BY tg.post_id HAVING COUNT(DISTINCT t.name) = 7) 

使用JOIN

 SELECT p.* FROM POSTS p JOIN (SELECT tg.post_id FROM TAGGINGS tg JOIN TAGS t ON t.id = tg.tag_id WHERE t.name IN ('Cheese','Wine','Paris','Frace','City','Scenic','Art') GROUP BY tg.post_id HAVING COUNT(DISTINCT t.name) = 7) x ON x.post_id = p.id 

使用EXISTS

 SELECT p.* FROM POSTS p WHERE EXISTS (SELECT NULL FROM TAGGINGS tg JOIN TAGS t ON t.id = tg.tag_id WHERE t.name IN ('Cheese','Wine','Paris','Frace','City','Scenic','Art') AND tg.post_id = p.id GROUP BY tg.post_id HAVING COUNT(DISTINCT t.name) = 7) 

说明

事情的关键是COUNT(DISTINCT t.name)需要匹配标签名称的数量,以确保所有这些标签与post相关。 如果没有DISTINCT,其中一个名称的重复可能会返回7的数量 – 因此您会有误报。

性能

大多数人会告诉你JOIN是最优的,但是JOIN还冒着重复结果集中的行的风险。 EXISTS将是我的下一个选择 – 没有重复的风险,通常执行速度更快,但检查解释计划最终将根据您的设置和数据告诉您什么是最好的。

试试这个:

 Select * From Posts p Where Not Exists (Select * From tags t Where name in ('Cheese', 'Wine', 'Paris', 'Frace', 'City', 'Scenic', 'Art') And Not Exists (Select * From taggings Where tag_id = t.Tag_Id And post_Id = p.Post_Id)) 

说明 :询问那些已经拥有与之关联的指定标记集中的每一个的post的列表, 等同于询问那些在同一指定集合中没有标记的post,这些post没有与之关联。 即,上面的sql。