Проблема структурирования MySQL-запроса с одним-ко-многим по нескольким таблицам - PullRequest
0 голосов
/ 22 октября 2010

У меня есть приложение в стиле блога, которое позволяет пользователям отмечать каждый пост темами. Я храню эти данные в трех отдельных таблицах: сообщения (для фактических сообщений в блоге), темы (для различных тегов) и 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       |
+---------+-------------+-----------+----------------+

Я пробовал этот простой запрос с n успехом:

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 (см. здесь ).

Я также готов выслушать любые предложения, когда я запускаю два запроса и пытаюсь создать массив для каждого результата; Я попробовал это с приведенным ниже кодом, но потерпел неудачу (этот код также включает в себя присоединение к пользовательской таблице, что было бы неплохо также сохранить это):

    $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;
    }

Любая помощь с благодарностью.

Ответы [ 2 ]

1 голос
/ 22 октября 2010

Святая корова, ты можешь сделать это! Видите, это помогает помочь. Никогда не знал, попробуйте это Выбрать post_id, GROUP_CONCAT (DISTINCT topic_name) как имена ОТ сообщения, post_topics, темы ГДЕ post_topic_topic_id = topic_id AND post_topic_post_id = post_id

GROUP BY post_id;

Вы получаете 1, «политика, религия» 2, «спорт, религия»

1 голос
/ 22 октября 2010

Этот запрос должен помочь. Просто измените * на список полей, который вы хотите, чтобы вы не извлекали лишние данные каждый раз, когда выполняете запрос.

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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...