2010-10-21 5 views
0

J'ai une application de style blog qui permet aux utilisateurs d'étiqueter chaque article avec des sujets. Je conserve ces données dans trois tableaux distincts: les posts (pour les articles de blog réels), les rubriques (pour les différents tags) et posts_topics (une table qui stocke les relations entre les deux). Afin de garder la structure MVC (j'utilise Codeigniter) aussi propre que possible, je voudrais exécuter une requête MySQL qui saisit toutes les données de poste et les données de sujet associées et les renvoie dans un tableau ou un objet . Jusqu'à présent, je n'ai pas de chance.Problème de structuration de la requête MySQL avec un-à-plusieurs sur plusieurs tables

La structure de la table est comme ceci:

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  | 
+---------+-------------+-----------+----------------+ 

J'ai essayé cette simple requête avec succès 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 

J'ai aussi essayé d'utiliser GROUP_CONCAT, mais qui me donne deux problèmes: 1) J'ai besoin de tous les champs de Sujets, pas seulement les noms, et 2) J'ai un problème dans mon MySQL, donc toutes les données GROUP_CONCAT sont renvoyées en tant que BLOB (voir here).

Je suis également ouvert à toute suggestion où j'exécute deux requêtes et essaie de construire un tableau pour chaque résultat; J'ai essayé avec le code ci-dessous, mais a échoué (ce code comprend également se joindre à la table des utilisateurs, ce qui serait formidable de garder cela aussi):

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

Toute aide grandement appréciée.

Répondre

1

Cette requête devrait faire l'affaire. Remplacez simplement le * par la liste de champs que vous désirez afin de ne pas extraire des données en excès chaque fois que vous lancez la requête.

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

Merci pour la réponse, mais cela me donne plusieurs résultats de chaque poste - un pour chaque sujet associé au poste. J'en ai besoin pour retourner le message une seule fois, puis retourner tous les sujets associés à la publication. – tchaymore

+1

Vous devrez parcourir le jeu de résultats et assembler le tableau en PHP. $ myArray = array(); $ rs = mysql_fetch_assoc ($ q); $ last_post_id = $ rs ['post_id']; $ topics = ""; do { if ($ last_post_id! = $ Rs ['post_id']) { $ myArray [] = tableau ($ last_post_id => $ topics); $ topics = ""; $ last_post_id = $ rs ['post_id']; } $ topics. = $ Rs ["topic_name"]. ""; } while ($ rs = mysql_fetch_assoc ($ q); – Jim

+0

J'ai eu quelques problèmes pour structurer le tableau pour une raison quelconque, mais j'ai réussi à le faire. – tchaymore

1

Sainte vache, vous pouvez le faire! Voir cela aide à aider. N'a jamais su, essayez ce Sélectionnez post_id, GROUP_CONCAT (DISTINCT TOPIC_NAME) en tant que noms DE messages, post_topics, sujets OÙ post_topic_topic_id = topic_id ET post_topic_post_id = post_id

GROUP BY post_id;

Vous obtenez 1, « la politique, relligion » 2, « le sport, relligion »

+0

Vous avez raison, Group_Concat m'obtiendrait les noms des sujets, mais dans ce cas, je voulais saisir plus de données de la table des sujets, donc j'ai suivi le conseil dans votre première réponse. – tchaymore

+0

Vous pouvez utiliser la requête GROUP_CONCAT en tant que sous-requête de celle qui renvoie les données supplémentaires dont vous avez besoin. – Jim

+0

SELECT * , (Select GROUP_CONCAT (DISTINCT TOPIC_NAME) en tant que noms de messages, post_topics, sujets OÙ post_topic_topic_id = topic_id ET post_topic_post_id = post_id) en tant que sujets DE messages, utilisateurs OÙ user_id = post_user_id; – Jim