[RESOLU] Afficher les résultats (en intercalé) de deux tables MySQL

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

24 févr. 2015, 15:44

Le principe consiste en fait à combiner les résultats des deux requêtes pour générer une liste d'enregistrement que tu peux ensuite interroger.

Concrètement, la première requête retourne un tableau de résultat avec uniquement les sujets

Code : Tout sélectionner

type_message | p.id | p.id_forum | p.titre_rewrite | p.titre | p.date_ajout ------------------------------------------------------------------------------------------- topic | 1 | 1 | Titre Sujet 1 | Titre Sujet 1 | 01/02/2015 topic | 2 | 1 | Titre Sujet 2 | Titre Sujet 2 | 10/02/2015
la seconde requête retourne un tableau de résultat avec uniquement les réponses, et les informations des sujets auxquelles elles répondent

Code : Tout sélectionner

type_message | m.id_post | p.id_forum | p.titre_rewrite | p.titre | m.date_ajout ------------------------------------------------------------------------------------------- answer | 1 | 1 | Titre Sujet 1 | Titre Sujet 1 | 05/02/2015 answer | 2 | 1 | Titre Sujet 2 | Titre Sujet 2 | 15/02/2015 answer | 3 | 1 | Titre Sujet 1 | Titre Sujet 1 | 20/02/2015
La commande UNION ALL, te permet de regrouper les deux tableaux dans un seul. Il est donc indispensable que chaque requête retourne le même nombre de champ, de même type et dans le même ordre pour conserver la structure du tableau :

Code : Tout sélectionner

type_message | ? | p.id_forum | p.titre_rewrite | p.titre | ?.date_ajout ------------------------------------------------------------------------------------------- topic | 1 | 1 | Titre Sujet 1 | Titre Sujet 1 | 01/02/2015 topic | 2 | 1 | Titre Sujet 2 | Titre Sujet 2 | 10/02/2015 answer | 1 | 1 | Titre Sujet 1 | Titre Sujet 1 | 05/02/2015 answer | 2 | 1 | Titre Sujet 2 | Titre Sujet 2 | 15/02/2015 answer | 3 | 1 | Titre Sujet 1 | Titre Sujet 1 | 20/02/2015
Enfin le "SELECT * FROM (###) ORDER BY date_ajout" te permet de trier ce tableau comme tu l'entends, (###) étant finalement une vue de ta base de données.

Code : Tout sélectionner

type_message | ? | p.id_forum | p.titre_rewrite | p.titre | ?.date_ajout ------------------------------------------------------------------------------------------- answer | 3 | 1 | Titre Sujet 1 | Titre Sujet 1 | 20/02/2015 answer | 2 | 1 | Titre Sujet 2 | Titre Sujet 2 | 15/02/2015 topic | 2 | 1 | Titre Sujet 2 | Titre Sujet 2 | 10/02/2015 answer | 1 | 1 | Titre Sujet 1 | Titre Sujet 1 | 05/02/2015 topic | 1 | 1 | Titre Sujet 1 | Titre Sujet 1 | 01/02/2015
Tu peux ainsi parcourir le résultat et afficher la dernière réponse au sujet 1, puis la réponse au sujet 2, puis le sujet 2, puis une réponse au sujet 1 et enfin le sujet 1, ce qui correspond à l'ordre chronologique des posts :)

Quant à ajouter une colonne, il faut donc effectivement l'ajouter au même endroit dans les 2 requêtes. Sauf que " m.id ", c'est à dire " forum_messages.id ", qui fait donc référence à la colonne "id" de la table "forum_messages", n'est disponible que dans la seconde requête. Il te faut donc trouver l'équivalent dans la première requête qui ne sollicite pour le moment que la table forum_posts ;)

En espérant que maintenant ça soit plus clair :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Avatar du membre
Mammouth du PHP | 1564 Messages

24 févr. 2015, 17:38

C'est super bien expliqué, merci, donc si je modifie la structure de la table posts et que je rajoute un champ de type integer, je peut l'associer à id de la table messages ?

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

24 févr. 2015, 22:26

C'est une solution, mais si cette information ne te sert à rien, pas besoin de modifier la structure de tes tables, tu peux simplement utiliser une constante dans la première requête :
SELECT *
FROM (
    SELECT 'topic' AS type_message, 0 as id_message, p.id, p.id_forum, p.titre_rewrite,p.titre,p.date_ajout FROM forum_posts p
    UNION ALL
    SELECT 'answer' AS type_message, m.id as id_message, m.id_post, p.id_forum, p.titre_rewrite,p.titre,m.date_ajout FROM forum_messages m JOIN forum_posts p ON m.id_post = p.id
) a
ORDER BY date_ajout DESC
Lorsque tu exécutes cette requête, tu peux récupérer la "colonne" id_message qui contiendra 0 lorsque l'enregistrement est un topic, et "l'id" du message pour les enregistrement de type message :)

On a bien le même nombre de champ retournés par les deux requêtes, les deux sont des données numériques et pas besoin de toucher à tes tables ;)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Avatar du membre
Mammouth du PHP | 1564 Messages

25 févr. 2015, 01:48

Cool, merci, admettons, je doit récupérer un autre champ de la table messages et cette fois ci c'est un string, je peut mettre 'blablabla' au lieu de 0, par exemple ?

2ème question: tu à mis le 0 avant le AS, c'est une porte de secours, ou le zéro peut être placé avec les p.id, p.id_forum, p.tit... ?

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

25 févr. 2015, 15:00

Pour ajouter une chaîne de caractères, tu peux tout à fait mettre 'blabla', ou même une chaine vide '' ... l'important est de respecter le nombre et l'ordre des éléments retournés par chaque requête.

Pour le 0, je l'ai en fait mit au même endroit que le m.id dans la 2nd requête. On pourrait tout à fait mettre ceux-ci à la fin, au milieu ou au début de la requête tant qu'ils sont à la même position dans les deux requêtes pour être regroupés une fois les résultats réunifiés par le UNION.

Quant au AS, c'est en fait pour te permettre de donner un alias / un nom, à la colonne afin de pouvoir lire celle-ci avec un mysql_fetch_assoc(). En l'occurrence, quand tu rajoutes la constante 0, elle n'a pas de nom. En lui donnant un alias (0 as id_message), tu pourras utiliser cet index pour accéder à cette valeur :
$row = mysql_fetch_assoc($rs);
echo $row['id_message']; // Affichera 0 pour les enregistrement de type topic, et l'id du message pour les autres
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Avatar du membre
Mammouth du PHP | 1564 Messages

25 févr. 2015, 19:25

Oui, bien sûr, j'avais pas vu que le AS était pour l'id, je pensais que c'était celui du answer et topic.

T'es réponses m'ont été d'une utilité énorme et je t'en remercie, bonne continuation !