假设我有以下表格:
id:整数 名称:字符串
id:整数 正文:文本
id:整数 tag_id:整数 post_id:整数
我将如何编写一个查询来选择所有带有以下所有标记(标记表的名称属性)的标记的查询:“奶酪”,“葡萄酒”,“巴黎”,“宽限期”,“城市”,“风景区”,“艺术”
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的计数,因此存在误报的风险。
COUNT(DISTINCT t.name)
大多数人会告诉您JOIN是最佳的,但JOIN也会冒着重复结果集中的行的风险。EXISTS是我的下一个选择- 不会有重复的风险,并且执行速度通常会更快,但是检查说明计划最终将根据您的设置和数据告诉您哪种方法最好。