2014-02-11 82 views
0

過濾標籤我有以下查詢過濾掉基於一系列的限制條件線程行:查詢我還沒有機會測試的與COUNT

SELECT * 
    FROM threads th 
     JOIN v_threads_with_tags AS twt  /*Only if filtering by tags*/ 
      ON th.thread_id = twt.thread_id 
     JOIN v_friends AS f     /*Only if filtering to threads from friends*/ 
      ON th.owner_id = f.friend 
     LEFT JOIN v_visible_threads AS v   
      ON v.thread_id = th.thread_id 
    WHERE (v.viewer_id = 43 || v.viewer_id IS NULL) 
    && (v.friend_id = 43 || v.friend_id IS NULL)  
    && user = 43;       
    && tag_name IN ('foo','bar') 

零件,但我可以說確保標籤名稱未被完全過濾。該查詢如將返回設置類似這樣(只列出了相關的列)結果:

thread_id | tag_name 
    1   foo 
    1   bar 
    2   foo 
    3   foo 

我想要一個結果集只的thread_id的這兩篇文章在查詢中列出的所有的標籤,顯然我可以」沒有重複。在上面的例子中,我想要一個只有一個線程#1實例的結果集。

我已經在stackoverflow上看到類似的問題(請在將其標記爲重複項之前閱讀),並且提供的解決方案差別很大,但一般路由似乎通常涉及在查詢結尾添加以下語句:

HAVING COUNT('tag_name') = 2 

我也試過類似如下的查詢:

SELECT th.thread_id,th.owner_id,th.message,th.time,tag_name,viewer_id,v.friend_id 
    FROM threads th 
     LEFT JOIN v_visible_threads AS v 
      ON v.thread_id = th.thread_id 
    WHERE (v.viewer_id = 43 || v.viewer_id IS NULL) 
    && (v.friend_id = 43 || v.friend_id IS NULL) 
    && th.thread_id IN 
    (
     SELECT thread_id FROM v_threads_with_tags 
     WHERE tag_name IN ('foo','bar') 
     HAVING COUNT(tag_name) = 2 
    ) 

我很難理解在任一使用COUNT()。在這個結果集中,tag_name字段有四個值,所以我希望COUNT(tag_name)返回4,不管tag_name在特定行中的值是什麼。這實際上是它返回的值,所以該語句會使查詢返回一個空集。

不過,我看到這句話被無處不在用來解決這類問題,所以我必須假設每個人都正確使用它,並且我錯過了一些東西。

有人可以向我解釋我是否正確理解COUNT,以及我可能用什麼方法來完成我的查詢?

+0

如果你的'HAVING'行後加上'GROUP BY tag_name'發生了什麼(但仍在括號內)? – neokio

回答

1

如果你想線程有所有標籤,你不能只使用where條款。相反,按thread_id進行彙總並計算每個標籤的匹配數量。返回爲每個你關心的標籤至少有一個匹配的主題:

SELECT th.thread_id 
FROM threads th JOIN 
    v_threads_with_tags twt  /*Only if filtering by tags*/ 
    ON th.thread_id = twt.thread_id JOIN 
    v_friends f     /*Only if filtering to threads from friends*/ 
    ON th.owner_id = f.friend LEFT JOIN 
    v_visible_threads AS v   
    ON v.thread_id = th.thread_id 
WHERE (v.viewer_id = 43 || v.viewer_id IS NULL) and 
     (v.friend_id = 43 || v.friend_id IS NULL) and 
    user = 43 
group by th.thread_id 
having sum(tag_name = 'foo') > 0 and 
     sum(tag_name = 'bar') > 0;