2010-10-21 83 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