SQL Query用于匹配具有/不具有所有已定义的多对多匹配的记录

时间:2013-05-23 10:22:36

标签: mysql sql select many-to-many

我有三张桌子poststags,& postTags。正如您可能猜到的那样,posts包含有关博客帖子的信息,tags包含有关系统中正在使用的标记的信息,postTags包含posts之间的关系和tags

现在,让我们假设我知道我正在寻找的每个标签的tagID,以及我不知道的,什么是合适的,什么是合适的查询来获取所有{{1符合我在一个列表中指定的所有posts的条件,并且没有我在另一个列表上指定的条件?

我可以解决的一个方法是:

tagID

此查询将选择已由tagID 2&标记的所有帖子。 3,并没有用tagID 5标记。但这似乎可能很慢,特别是当数据被大量标签过滤时。

修改

SQL Fiddle

3 个答案:

答案 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