2011-05-29 49 views
3

我有一個'articles'表,並且我有一個'tags'表。這兩者之間有一個N:N的關係,所以我也有一個'articles_tags_relations'表。我想檢索帶有標籤的文章列表,但除了標籤的名稱之外,我也需要它的標識。因此,返回的數據應該是這樣的(當然不是JSON格式):如何檢索具有1:N關係的列表

[[1,"FirstArticle",{"1":"FirstTag","2":"SecondTag"}],[2,"SecondArticle",{"3":"ThirdTag"}]] 

到目前爲止,我有這樣的:

SELECT article.*, GROUP_CONCAT(tag.name SEPARATOR ', ') AS tags FROM articles AS article LEFT JOIN articles_tags_relations AS relation ON article.id = relation.article_id LEFT JOIN tags AS tag ON relation.tag_id = tag.id LIMIT 0,10; 

但它只有沒有IDS的標記名稱。在桌上會有很多閱讀查詢,所以表現很重要。我不確定使用GROUP_CONCAT是要走的路,我願意接受任何想法。謝謝!

回答

0

你幾乎在那裏。添加CONCAT以獲得id和記錄,或爲每個條目創建單獨的GROUP_CONCAT子句。

SELECT article.*, 
    GROUP_CONCAT(CONCAT(tag.id,':',tag.name)) AS tags 
FROM articles AS article 
LEFT JOIN articles_tags_relations AS relation ON article.id = relation.article_id 
LEFT JOIN tags AS tag ON relation.tag_id = tag.id 
GROUP BY article.id 
LIMIT 0,10 

AFAIK沒有什麼特別的關於GROUP_CONCAT會造成性能損失。


只是爲了好玩這裏是一個查詢將返回一個JSON

SELECT CONCAT('[',GROUP_CONCAT(CONCAT('[',row_data,']')),']') as JSON 
FROM 
(
    SELECT CONCAT(a.id,',"',a.title,'",{',GROUP_CONCAT(CONCAT("'",tag.id,'":"',tag.name,'"')),'}') as row_data 
    FROM articles AS a 
    LEFT JOIN articles_tags_relations AS relation ON a.id = relation.article_id 
    LEFT JOIN tags AS tag ON relation.tag_id = tag.id 
    GROUP BY a.id 
    LIMIT 0,10 
) t1 
1

您是否必須在一個查詢中執行此操作?我會做一個查詢來獲取文章,然後第二個獲取這些文章ID的標籤。雖然我不確定性能如何。 (它可能取決於你的網絡速度,第二個查詢的成本與左連接的成本。)

這就是說,試圖連接sql查詢中的多個數據片段感覺就像它違背一個關係數據庫,不太可能像數據庫真正擅長的那樣執行。

+0

不,不是重要的做在一個查詢。所以你說我應該做下面的事情? SELECT article。* FROM articles; SELECT標籤* FROM articles_tags_relations AS關係LEFT JOIN標籤AS標籤ON relation.tag_id = tag.id WHERE relation.article_id IN(1,2,3,4,5,...); – 2011-05-29 20:38:45

+0

通常,我會做Marcel提出的建議(除了外部連接)。在你的情況下,我明白不這樣做,因爲你不想多次發送文章文本由於性能/帶寬。所以是的,我會對你描述的兩個問題。幾乎。您仍然需要第二個查詢中的article_id,以便您知道哪個標籤隨文章而發生變化。目標是將文章文本從加入的查詢中移出。 – 2011-05-29 20:51:00

1

據我所知,GROUP_CONCAT()GROUB BY條款一起使用。但是,這裏有接收tag.id與您的數據的兩個備選方案:

SELECT article.*, tag.id AS tags_id, GROUP_CONCAT(tag.name SEPARATOR ', ') AS tags FROM articles AS article LEFT JOIN articles_tags_relations AS relation ON article.id = relation.article_id LEFT JOIN tags AS tag ON relation.tag_id = tag.id LIMIT 0,10; 

和2:

SELECT article.*, GROUP_CONCAT(tag.name SEPARATOR ', ') AS tags, GROUP_CONCAT(tag.id SEPARATOR ', ') AS tag_ids FROM articles AS article LEFT JOIN articles_tags_relations AS relation ON article.id = relation.article_id LEFT JOIN tags AS tag ON relation.tag_id = tag.id LIMIT 0,10; 
0

對不起,我似乎不明白你的問題。對我來說,解決方案很簡單:select a.id, a.name, t.id, t.name from articles a, tags t, articles_tags_relations atr where a.id = atr.article_id and t.id = atr.tag_id

當然,這不會根據需要格式化結果,但格式化不是SQL的意思。首先檢索結果(參見上文),然後使用您選擇的編程語言對結果集進行格式設置。

+0

一篇文章可以有多個標籤。在你的SQL查詢中,只有一個標籤被檢索到。 – 2011-05-29 20:41:52

+0

不,當然不是。結果集看起來像「1條1 1標籤1/1條1標籤2/1條1標籤3」等等。我提到它不會很好地格式化,但。 – 2011-05-30 08:25:16