2013-07-27 31 views
0

我有一個使用參考表tags_titlestags_blogs來比較保存標籤叫標籤表下面的查詢。標籤本身保存在t.label列中。Mysql的內部連接管理計數()行爲

我的問題是,有時它count()過多total_matches。通常可以在tags_titles和tags_blogs中找到標記。有沒有辦法讓內部連接相互排斥或其他解決方案,以便與t.label列的實際匹配計數是準確的?

SELECT b.blog_id AS id, b.title AS title, b.body AS body, COUNT(t.label) AS total_matches, b.creation_time AS creation_time, '1' AS type 
FROM tags AS t 
INNER JOIN tags_titles AS tt 
ON tt.tag_id = t.tag_id 
INNER JOIN tags_blogs AS tb 
ON tb.tag_id = t.tag_id 
INNER JOIN blogs AS b 
ON tt.blog_id=b.blog_id OR tb.blog_id=b.blog_id 
WHERE t.label IN ($in) AND b.title IS NOT NULL 
GROUP BY id, title, body, creation_time, type 
+0

你能提供的小提琴例子,你想要的結果集 –

+0

我會嘗試從來沒有使用過小提琴 –

+1

之前儘量把你的查詢中使用的表模式,然後構建模式和運行查詢那裏,讓你的提琴的http:// sqlfiddle.com/ –

回答

4

您的問題是,有一個標籤和博客標籤列表的標籤列表,你會得到這些標籤的Cartesian產品爲每個博客。

簡單的解決問題的方法是使用count(distinct)

SELECT b.blog_id AS id, b.title AS title, b.body AS body, COUNT(distinct t.label) AS total_matches, 
     b.creation_time AS creation_time, '1' AS type 
FROM tags AS t 
INNER JOIN tags_titles AS tt 
ON tt.tag_id = t.tag_id 
INNER JOIN tags_blogs AS tb 
ON tb.tag_id = t.tag_id 
INNER JOIN blogs AS b 
ON tt.blog_id=b.blog_id OR tb.blog_id=b.blog_id 
WHERE t.label IN ($in) AND b.title IS NOT NULL 
GROUP BY id, title, body, creation_time, type; 

在更復雜的情況下,有時需要沿着不同的尺寸分別聚集加入之前。

您還有一個問題,就是t.label in ($in)。這不適用於英寸。您可以使用:

find_in_set(t.label, $in) > 0; 

或者在SQL中直接替換列表。前一種方法不使用索引進行過濾。後者將(如果有適當的一個可用)。

+0

這似乎是工作。對你對IN的比較感興趣...我正在做的是使用mysqli並代替一些?,?,?作爲$ in取決於輸入了多少搜索詞。與IN有關的結構問題嗎? –

+1

@AmyNeville。 。 。如果每個值都有單獨的變量,則沒有問題。我的印象是'$ in'就像''a,b,c''。在這種情況下,它被解釋爲包含逗號的一個值,而不是三個逗號分隔值。 –

+0

是的,經歷了這個找出如何在mysqli中使用call_user_func_array()的整個折磨過程 - 非常感謝您的幫助! :) –