2011-02-09 116 views
2

我想選擇包含特定標記的所有文章。我與這個查詢嘗試它:sql連接問題

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標籤的帖子o只是)

+0

RIGHT JOIN?你確定這就是你想要的嗎? –

+0

你說得對,我不需要那個,但仍然不能工作 – networkprofile

+0

你能提供樣本數據和你的預期輸出嗎? –

回答

3
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 
+0

謝謝,我不認爲我會發現這一點。仍然不明白最底層的兩個連接是如何工作的。 – networkprofile

+0

+1不使用子查詢,只使用INNER JOIN。 –

+1

@Sled:底部的兩個連接與前兩個連接相同,除了它們還包含條件'AND t2.tag_name ='php''。因爲他們是INNER連接,他們保證返回的任何帖子都必須將php標籤關聯。 –

2

我會盡力解釋爲什麼你的第一次嘗試不起作用。

你真正想做的是找到所有帖子其中一個的標籤是'php'。 但他們的標籤分佈在多行因此t.tag_name = 'php'不起作用,因爲它過濾掉沒有'php'標籤的所有行。

當你想檢查取決於許多行的條件,

您可以創建一個子查詢(發現確實有PHP代碼的所有post_ids)

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_ids與所有相關標籤。

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個連接(即作用類似於一個子查詢)

+0

我明白了,謝謝你們麻煩解釋! – networkprofile