假设我有以下表格:
id:整数
name:string
id:整数
body:text
id:整数
tag_id:整数
post_id:整数
我如何编写一个查询,选择所有标记有以下所有标记的帖子(标签表的名称属性):“Cheese”,“Wine”,“Paris”,“Frace”,“City” “,”风景“,”艺术“
另请参阅:Need help with sql query to find things with most specified tags(注意:类似,但不重复!)
答案 0 :(得分:17)
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)
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
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)
需要匹配标记名称的数量,以确保所有这些标记与帖子相关。如果没有DISTINCT,其中一个名称的重复可能会返回7的数量 - 这样你就会产生误报。
大多数人都会告诉你JOIN是最优的,但是JOIN还冒着重复结果集中的行的风险。 EXISTS将是我的下一个选择 - 没有重复的风险,通常执行速度更快,但检查解释计划最终将根据您的设置和数据告诉您什么是最好的。
答案 1 :(得分:2)
试试这个:
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))
解释:要求列出那些与 em> 要求那些没有标记的帖子在同一个指定的集合中, 不 与之关联。即,上面的sql。