我有三张桌子posts
,tags
,& postTags
。正如您可能猜到的那样,posts
包含有关博客帖子的信息,tags
包含有关系统中正在使用的标记的信息,postTags
包含posts
之间的关系和tags
。
现在,让我们假设我知道我正在寻找的每个标签的tagID
,以及我不知道的,什么是合适的,什么是合适的查询来获取所有{{1符合我在一个列表中指定的所有posts
的条件,并且没有我在另一个列表上指定的条件?
我可以解决的一个方法是:
tagID
此查询将选择已由tagID 2&标记的所有帖子。 3,并没有用tagID 5标记。但这似乎可能很慢,特别是当数据被大量标签过滤时。
修改
答案 0 :(得分:2)
您可以尝试使用EXISTS策略优化查询:
SELECT
`posts`.*
FROM
`posts`
WHERE
EXISTS (
SELECT 1 FROM `postTags`
WHERE `postTags`.`postID` = `posts`.`postID`
AND `postTags`.`tagID` = 2
)
AND
EXISTS (
SELECT 1 FROM `postTags`
WHERE `postTags`.`postID` = `posts`.`postID`
AND `postTags`.`tagID` = 3
)
AND NOT EXISTS (
SELECT 1 FROM `postTags`
WHERE `postTags`.`postID` = `posts`.`postID`
AND `postTags`.`tagID` = 5
)
答案 1 :(得分:1)
我会加入几个子选择,避免相关的子查询。
如下所示(不确定您是否需要SELECT中的标记连接列表,但暂时将其留在那里)
SELECT `posts`.*,
CONCAT(',', Sub1.TagList, ',') AS `pTags`
FROM `posts`
INNER JOIN (
SELECT postID, GROUP_CONCAT(`postTags`.`tagID`) AS TagList, COUNT(*) AS TagCount
FROM postTags
WHERE tagID IN (2, 3)
GROUP BY postID
HAVING TagCount = 2
) Sub1
ON posts.postID = Sub1.postID
LEFT OUTER JOIN (
SELECT postID
FROM postTags
WHERE tagID IN (5)
) Sub2
ON posts.postID = Sub2.postID
WHERE Sub2.postID IS NULL
答案 2 :(得分:1)
我相信它会带来你想要的帖子。
SELECT
p.*, GROUP_CONCAT(pt.tagID)
FROM
posts p
inner join postTags pt on p.postID = pt.postID
WHERE
not exists (
SELECT
1
FROM
Tags t
WHERE
t.tagID in (2,3)
AND not exists
(
select 1 from postTags pt where pt.postID = p.postID and pt.tagID = t.tagID
)
)
and not exists(
SELECT
1
FROM
Tags t
WHERE
t.tagID in (5)
AND exists
(
select 1 from postTags pt where pt.postID = p.postID and pt.tagID = t.tagID
)
)
GROUP BY p.postID