2010-10-21 12 views
0

我有一個博客樣式的應用程序,允許用戶使用主題標記每個帖子。我將這些數據保存在三個獨立的表格中:帖子(用於實際的博客文章),主題(用於各種標籤)和posts_topics(存儲兩者之間關係的表格)。在多個表上使用一對多來構建MySQL查詢問題

爲了保持MVC結構(我使用Codeigniter)儘可能乾淨,我想運行一個MySQL查詢來抓取所有發佈數據和關聯主題數據,並將其返回到一個數組或對象中。到目前爲止,我沒有任何運氣。

表結構是這樣的:

Posts 
+--------+---------------+------------+-----------+--------------+---------------+ 
|post_id | post_user_id | post_title | post_body | post_created | post_modified | 
+--------+---------------+------------+-----------+--------------+---------------+ 
|  1 | 1   | Post 1  | Body 1 | 00-00-00 | 00-00-00  | 
|  2 | 1   | Post 1  | Body 1 | 00-00-00 | 00-00-00  | 
+--------+---------------+------------+-----------+--------------+---------------+ 

// this table governs relationships between posts and topics 
Posts_topics 
+--------------+---------------------+-------------------------+-----------------+ 
|post_topic_id | post_topic_post_id | post_topic_topic_id | post_topic_created | 
+--------------+---------------------+-------------------------+-----------------+ 
|  1  | 1    | 1     |   00-00-00 | 
|  2  | 1    | 2     |   00-00-00 | 
|  3  | 2    | 2     |   00-00-00 | 
|  4  | 2    | 3     |   00-00-00 | 
+--------------+---------------------+-------------------------+-----------------+ 

Topics 
+---------+-------------+-----------+----------------+ 
|topic_id | topic_name | topic_num | topic_modified | 
+---------+-------------+-----------+----------------+ 
|  1 | Politics | 1   | 00-00-00  | 
|  2 | Religion | 2   | 00-00-00  | 
|  3 | Sports  | 1   | 00-00-00  | 
+---------+-------------+-----------+----------------+ 

我曾嘗試與正成功這個簡單的查詢:

select * from posts as p inner join posts_topics as pt on pt.post_topic_post_id = post_id join topics as t on t.topic_id = pt.post_topic_topic id 

我使用GROUP_CONCAT也嘗試過,但是這給了我兩個問題: 1)我需要主題中的所有字段,而不僅僅是名稱,以及2)我的MySQL中有一個小故障,因此所有GROUP_CONCAT數據都以BLOB形式返回(請參閱here)。

我也樂於聽到任何建議,我運行兩個查詢,並嘗試爲每個結果構建數組;我想,下面,但失敗的碼(此代碼還包括加入用戶表,這將是巨大的,以保持這一以及):

$this->db->select('u.username,u.id,s.*'); 
    $this->db->from('posts as p'); 
    $this->db->join('users as u', 'u.id = s.post_user_id'); 
    $this->db->order_by('post_modified', 'desc'); 
    $query = $this->db->get(); 
    if($query->num_rows() > 0) 
    { 
     $posts = $query->result_array(); 
     foreach($posts as $p) 
     { 
      $this->db->from('posts_topics as p'); 
      $this->db->join('topics as t','t.topic_id = p.post_topic_topic_id'); 
      $this->db->where('p.post_topic_post_id',$p['post_id']); 
      $this->db->order_by('t.topic_name','asc'); 
      $query = $this->db->get(); 
      if($query->num_rows() > 0) 
      { 
       foreach($query->result_array() as $t) 
       { 
        $p['topics'][$t['topic_name']] = $t; 
       } 
      } 
     } 
     return $posts; 
    } 

任何幫助極大的讚賞。

回答

1

此查詢應該做的伎倆。只需將*更改爲您所需的字段列表,以便您不會在每次運行查詢時拉取多餘的數據。

Select 
    * 
FROM 
    posts, 
    post_topics, 
    topics 
WHERE 
    post_topic_topic_id = topic_id AND 
    post_topic_post_id = post_id 
ORDER BY 
post_id, topic_id; 

Select 
    * 
FROM 
    posts, 
    post_topics, 
    topics, 
    users 
WHERE 
    post_topic_topic_id = topic_id AND 
    post_topic_post_id = post_id AND 
    post_user_id = user_id 
ORDER BY 
post_id, topic_id; 
+0

感謝您的回答,但是,讓我的每一篇文章的多個結果 - 一個用於與帖子相關聯的每個主題。我需要它僅返回實際文章一次,然後返回與該文章相關的所有主題。 – tchaymore 2010-10-22 16:27:52

+1

您需要遍歷結果集並在PHP中組裝數組。 $ myArray = array(); $ rs = mysql_fetch_assoc($ q); $ last_post_id = $ rs ['post_id']; $ topics =「」;如果($ last_post_id!= $ rs ['post_id']){ $ myArray [] = array($ last_post_id => $ topics); $ topics =「」; $ last_post_id = $ rs ['post_id']; } $ topics。= $ rs ['topic_name']。 「」; } while($ rs = mysql_fetch_assoc($ q); – Jim 2010-10-22 17:53:19

+0

由於某種原因,我在構建數組時遇到了一些麻煩,但得到了這個工作。 – tchaymore 2010-10-24 00:34:34

1

聖牛,你可以做到!看到它有助於幫助。從來不知道,試試這個 選擇 POST_ID, GROUP_CONCAT(DISTINCT TOPIC_NAME)姓名 FROM 帖子, post_topics, 主題 WHERE post_topic_topic_id = topic_id和 post_topic_post_id = POST_ID

GROUP BY POST_ID;

你得到 1,「政治,relligion」 2,「體育,relligion」

+0

你是對的,Group_Concat會給我這些主題的名字,但在這種情況下,我想從主題表中獲取更多數據,所以我在第一個答案中遵循了建議。 – tchaymore 2010-10-24 00:35:04

+0

您可以使用GROUP_CONCAT查詢作爲返回所需額外數據的子查詢。 – Jim 2010-10-24 03:34:31

+0

選擇 *, (選擇GROUP_CONCAT(DISTINCT TOPIC_NAME)的名字來自帖子,post_topics,主題WHERE post_topic_topic_id = topic_id和post_topic_post_id = POST_ID)爲主題 FROM 帖子, 用戶 WHERE USER_ID = post_user_id; – Jim 2010-10-24 03:42:42