sql join问题

时间:2011-02-09 20:26:58

标签: php sql join

我想选择包含特定标记的所有帖子。我正在尝试这个查询:

SELECT GROUP_CONCAT(t.tag_name) taglist
FROM posts p
JOIN posts_tags pt ON p.post_id = pt.post_id
JOIN tags t ON t.tag_id = pt.tag_id
WHERE (p.post_private = 0) AND t.tag_name = 'php'
GROUP BY p.post_id

问题是,上面的查询会选择包含php标记的所有帖子,但不会选择帖子中可能包含的任何其他标记。如果没有AND t.tag_name = 'php'部分,它会选择帖子中的每个标记,但我希望能够按标记进行过滤...

任何想法如何做到这一点?我尝试了很多东西,但无法弄明白......

没有AND声明的示例数据:

|| *taglist* ||
|| php,echo  ||
|| c++, cout ||

使用AND语句的示例数据:

|| *taglist* ||
|| php       ||

我想要的是什么:

|| *taglist* ||
|| php,echo  ||

(仅包含PHP标记的帖子)

2 个答案:

答案 0 :(得分:2)

SELECT p.post_id, GROUP_CONCAT(t.tag_name) taglist
    FROM posts p
        /* These 2 joins get the list of all tags */
        INNER JOIN posts_tags pt
            ON p.post_id = pt.post_id
        INNER JOIN tags t
            ON pt.tag_id = t.tag_id
        /* These 2 joins guarantee the 'php' tag is included */
        INNER JOIN posts_tags pt2
            ON p.post_id = pt2.post_id
        INNER JOIN tags t2
            ON pt2.tag_id = t2.tag_id
                AND t2.tag_name = 'php'
    WHERE p.post_private = 0
    GROUP BY p.post_id

答案 1 :(得分:1)

我会尝试解释为什么你的第一次尝试不起作用。

您真正要做的是找到所有一个标签的帖子都是'php'。 但是他们的标记会在多行中传播,因此t.tag_name = 'php'无效,因为它会过滤掉所有没有'php'标记的行。

如果要检查依赖于多行的条件,

你要么创建一个子查询(找到所有有php标签的post_id)

  p.post_id IN
  ( SELECT pt2.post_id
      FROM post_tags pt2 
        JOIN tags t2
          ON t2.tag_id = pt2.tag_id
      WHERE t2.tag_name = 'php'
  )

但仍然使用所有相关标签加入这些post_id。

SELECT GROUP_CONCAT(t.tag_name) taglist
  FROM posts p
    JOIN posts_tags pt
      ON p.post_id = pt.post_id
    JOIN tags t
      ON t.tag_id = pt.tag_id
  WHERE (p.post_private = 0) 
    AND p.post_id IN
      ( SELECT pt2.post_id
          FROM post_tags pt2 
            JOIN tags t2
              ON t2.tag_id = pt2.tag_id
          WHERE t2.tag_name = 'php'
      )
  GROUP BY p.post_id

或者你更聪明地做到这一点,因为Stefanelli展示了另外2个JOIN(其行为类似于子查询)