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

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : [RESOLU] Afficher les résultats (en intercalé) de deux tables MySQL

Re: [RESOLU] Afficher les résultats (en intercalé) de deux t

par two3d » 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 !

Re: [RESOLU] Afficher les résultats (en intercalé) de deux t

par Ryle » 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

Re: [RESOLU] Afficher les résultats (en intercalé) de deux t

par two3d » 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... ?

Re: [RESOLU] Afficher les résultats (en intercalé) de deux t

par Ryle » 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 ;)

Re: [RESOLU] Afficher les résultats (en intercalé) de deux t

par two3d » 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 ?

Re: [RESOLU] Afficher les résultats (en intercalé) de deux t

par Ryle » 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 :)

Re: [RESOLU] Afficher les résultats (en intercalé) de deux t

par two3d » 24 févr. 2015, 12:43

Merci beaucoup pour votre aide, ça fonctionne nikel, je comprend pas tout mais c'est mieux que rien :D

Je souhaiterais ajouter l'id du message qui à été ajouté au post, afin que je puisse mettre une ancre, au lien (lien#id du msg), j'ai donc essayé de mettre deux fois m.id dans les deux requêtes mais ça ne fonctionne pas.

Re: Afficher les résultats (en intercalé) de deux tables MyS

par Ryle » 16 févr. 2015, 18:19

C'est possible, il suffit de l'ajouter tout à la fin :)

Re: Afficher les résultats (en intercalé) de deux tables MyS

par two3d » 16 févr. 2015, 14:30

Chouette, merci, est il possible d'utiliser un LIMIT 0,10 avec cette requête ?

Re: Afficher les résultats (en intercalé) de deux tables MyS

par Ryle » 16 févr. 2015, 11:30

Le " a " est un alias donné au résultat de tes requêtes. En fait, le SELECT qui est autour et qui permet de trier tes enregistrement va interroger le résultat de ton UNION comme s'il interrogeait une table de la base de données. Cela permet simplement de donner un nom à cette "table virtuelle" :)

Pour que l'Union fonctionne, il faut que chacune des requêtes retourne le même nombre de colonne et dans le même ordre. Et pour récupérer les infos du topic dans ton message, c'est l'objet la jointure :)
SELECT *
FROM (
    SELECT 'topic' as type_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_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
J'ai également ajouté une constante (type_message) dans chaque requête qui te permettra de savoir si tu parcours un enregistrement de type sujet ou de type reponse pour pouvoir ajuster ton message à l'affichage :)

Re: Afficher les résultats (en intercalé) de deux tables MyS

par two3d » 16 févr. 2015, 02:05

Merci pour ta contribution

alors comment faire si je veut le titre de la table forum_post, dans ce cas ?

Re: Afficher les résultats (en intercalé) de deux tables MyS

par tof73 » 16 févr. 2015, 02:00

la, c'est une faute de frappe.
les 2 sous-requetes doivent retourner le même nombre de champs, et le même type de champs.

Re: Afficher les résultats (en intercalé) de deux tables MyS

par two3d » 16 févr. 2015, 01:32

Je n'y arrive toujours pas, c'est complexe ce truc, ça me retourne aucun résultat:
SELECT *
FROM (
    SELECT p.id,p.id_forum,p.titre_rewrite,p.titre,p.date_ajout FROM forum_posts p
    UNION ALL
    SELECT m.id_post,m.date_ajout FROM forum_messages m JOIN forum_posts p ON m.id_post = p.id
) a
ORDER BY date_ajout DESC
Fait moi une requête que j’étudierais par la suite, s'il te plaît

Re: Afficher les résultats (en intercalé) de deux tables MyS

par two3d » 16 févr. 2015, 01:17

Ok, merci pour l'info.

Le "a" à quelque chose à voir dans la requête (au dessus de ORDER BY) ?

Re: Afficher les résultats (en intercalé) de deux tables MyS

par Ryle » 16 févr. 2015, 01:13

J'ai juste donnée une structure de requête SQL. Si tu n'as pas de condition WHERE, il suffit de ne pas en mettre ;)
SELECT *
FROM (
    SELECT p.date_ajout, ... FROM forum_posts p -- récupère les sujets
    UNION ALL
    SELECT m.date_ajout, ... FROM forum_messages m JOIN forum_posts p ON ... -- récupère les messages avec jointure sur les sujets pour récupérer le titre
) a
ORDER BY date_ajout DESC