【问题标题】:Trouble structuring MySQL query with one-to-many over multiple tables在多个表上使用一对多构建 MySQL 查询时遇到问题
【发布时间】:2010-10-21 22:14:03
【问题描述】:

我有一个博客风格的应用程序,它允许用户用主题标记每个帖子。我将这些数据保存在三个单独的表中:posts(用于实际的博客文章)、topics(用于各种标签)和 posts_topics(存储两者之间关系的表)。

为了使 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;
    }

非常感谢任何帮助。

【问题讨论】:

    标签: php activerecord codeigniter mysql


    【解决方案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;
    

    【讨论】:

    • 感谢您的回答,但这给了我每篇文章的多个结果——与文章相关的每个主题都有一个结果。我需要它只返回一次实际的帖子,然后返回与帖子相关的所有主题。
    • 您需要遍历结果集并在 PHP 中组装数组。 $myArray = 数组(); $rs = mysql_fetch_assoc($q); $last_post_id = $rs['post_id']; $主题 = "";做 { if($last_post_id != $rs['post_id']) { $myArray[] = array($last_post_id => $topics); $主题 = ""; $last_post_id = $rs['post_id']; } $topics .= $rs['topic_name'] 。 " "; } while ($rs = mysql_fetch_assoc($q);
    • 由于某种原因,我在构建数组时遇到了一些麻烦,但让它起作用了。感谢您的建议。
    【解决方案2】:

    圣牛,你可以的!看到它有助于帮助。从来不知道,试试这个 选择 post_id, GROUP_CONCAT(DISTINCT topic_name) 作为名称 从 帖子, post_topics, 话题 在哪里 post_topic_topic_id = topic_id 和 post_topic_post_id = post_id

    分组依据 post_id;

    你得到 1、“政治、宗教” 2, '体育,宗教'

    【讨论】:

    • 你说得对,Group_Concat 会给我主题的名称,但在这种情况下,我想从主题表中获取更多数据,所以我遵循了你第一个答案中的建议。跨度>
    • 您可以将 GROUP_CONCAT 查询用作返回所需额外数据的查询的子查询。
    • SELECT *, (选择 GROUP_CONCAT(DISTINCT topic_name) 作为来自帖子的名称,post_topics,主题 WHERE post_topic_topic_id = topic_id AND post_topic_post_id = post_id) 作为主题来自帖子,用户 WHERE user_id = post_user_id;
    猜你喜欢
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 2013-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-18
    • 1970-01-01
    相关资源
    最近更新 更多