Partage
  • Partager sur Facebook
  • Partager sur Twitter

System de MP à plusieur utilisateurs

difficultés sur les jointures

Sujet résolu
    30 avril 2006 à 21:47:20

    Hello hello amis Zéro :)

    J'ai donc commencé à créer mon system de messages privés pour mon site. J'en avait dejà un, mais le code était pourri et il aurai été dur d'y intergrer un system pour la gestion de plusieurs participants aux conversations. J'ai donc décidé de le recoder.

    J'ai donc réflechi et j'ai trouvé une organisation de table qui me parrait pas trop mal.

    CREATE TABLE `membre`
    (
      `mbr_id` smallint(4) UNSIGNED NOT NULL AUTO_INCREMENT,
      `mbr_pseudo` varchar(25) NOT NULL DEFAULT '',
      KEY `id` (`mbr_id`)
    ) TYPE=MyISAM COMMENT='contient les membres du site' AUTO_INCREMENT=10 ;
    /*Il n'y a pas toute la table, le rest sert à rien pour ce topic*/



    CREATE TABLE `mp_mbr`
    (
      `mpmbr_id` smallint(4) UNSIGNED NOT NULL AUTO_INCREMENT,
      `mpmbr_mbr_id` smallint(4) UNSIGNED NOT NULL DEFAULT '0',
      `mpmbr_mp_id` smallint(4) UNSIGNED NOT NULL DEFAULT '0',
      PRIMARY KEY  (`mpmbr_id`),
      KEY `mpmbr_mbr_id` (`mpmbr_mbr_id`,`mpmbr_mp_id`)
    ) TYPE=MyISAM COMMENT='Contient les participants aux mp' AUTO_INCREMENT=4 ;



    CREATE TABLE `mp_msg`
    (
      `mpm_id` smallint(3) UNSIGNED NOT NULL AUTO_INCREMENT,
      `mpm_id_mps` smallint(3) UNSIGNED NOT NULL DEFAULT '0',
      `mpm_pseudo` smallint(4) UNSIGNED NOT NULL DEFAULT '0',
      `mpm_contenu` text NOT NULL,
      `mpm_date` int(10) UNSIGNED NOT NULL DEFAULT '0',
      PRIMARY KEY  (`mpm_id`)
    ) TYPE=MyISAM COMMENT='Contient les messages des mp' AUTO_INCREMENT=1 ;



    CREATE TABLE `mp_sujet`
    (
      `mps_id` smallint(3) UNSIGNED NOT NULL AUTO_INCREMENT,
      `mps_titre` varchar(255) NOT NULL DEFAULT '',
      `mps_auteur` smallint(4) UNSIGNED NOT NULL DEFAULT '0',
      `mps_nb_vue` smallint(3) UNSIGNED NOT NULL DEFAULT '0',
      `mps_nb_msg` smallint(3) UNSIGNED NOT NULL DEFAULT '0',
      `mps_last_id` smallint(2) UNSIGNED NOT NULL DEFAULT '0',
      PRIMARY KEY  (`mps_id`)
    ) TYPE=MyISAM COMMENT='Contient les sujets des mp' AUTO_INCREMENT=2 ;


    Donc, j'aimerai pourvoir afficher la liste TOUS les participants à la conversation lors du listage des differentes conversations existantes. (comme sur le sdz en gros :p)

    J'ai bien essayé de faire un truc du genre
    SELECT mp_id, mpmbr_mbr_id FROM mp_sujet LEFT JOIN mp_mbr ON mpmbr_mp_id = mp_id

    Ce code va bien m'afficher les differents participants de la conversations, mais sur 3 lignes differentes, hors je voudrai que les differents participants soient listés sur une seul ligne.
    En gros, j'obtient ça avec ma requête :

    Citation : ce que j'ai

    id = 1, participant 1,
    id = 1, participant 2,
    id = 1, participant 3,
    etc



    Or, moi je voudrai avoir :

    Citation : ce que je veux

    id = 1, participants 1, participants 2, participants 3, etc



    J'ai bien regardé pas mal de topics sur les optimisations pour mieux me renseigner sur les jointures, les sous-requetes, surtout ceux ou shepard explique :p , mais je vois pas trop comment appliquer mes connaissances (certe infimes :D ) à mon cas.

    Si vous avez des idées pour mon probleme :)

    Merci d'avance à ceux qui m'aideront ;)
    • Partager sur Facebook
    • Partager sur Twitter
      1 mai 2006 à 10:33:04

      Personne pour mon probleme :(
      • Partager sur Facebook
      • Partager sur Twitter
        1 mai 2006 à 10:48:45

        En une requête c'est assez compliqué ( sauf si tu utilises MySQL >= 5.0 ).

        Mais en deux requêtes, c'est possible :)

        Tout d'abord, récupères tous les MP où le gars participe:

        SELECT mps_id, mps_titre, ... FROM mp_sujet WHERE mps_id IN ( SELECT mpmbr_mp_id WHERE mpmbr_mbr_id = [ID_DU_MEMBRE_ICI];


        Ensuite, il faut récupérer tous les membres ayant participé à ces MP:

        Commence par imploder tous les id de mp dans une variable PHP ( $mp_ids ), ensuite voilà la requête:

        SELECT mpmbr_mbr_id, mpmbr_mp_id, mbr_pseudo FROM mp_mbr WHERE mpmbr_mp_id IN ( $mp_ids ) AND mpmbr_mbr_id <> [ID_DU_MEMBRE_ICI];


        Enfin, tu boucles sur les sujets, et tu regardes dans le tableau des membres quels mpmbr_mp_id correspondent au tableau créé par la deuxième requête ( stocke le résultat de la deuxième requête dans un tableau, n'utilises plus mysql_fetch_xxx ).

        Voilà, j'espère que c'était compréhensible :D:D:p

        Bonne chance :)
        • Partager sur Facebook
        • Partager sur Twitter
          1 mai 2006 à 10:54:31

          SELECT mps_id, mps_titre, ... FROM mp_sujet WHERE mps_id IN ( SELECT mpmbr_mp_id WHERE mpmbr_mbr_id = [ID_DU_MEMBRE_ICI];

          C'est super lent, n'utilise pas ca :D
          Utilise plutot ca :
          SELECT mps_id, mps_titre, ... FROM mpmbr_mp_id LEFT JOIN mp_sujet ON mps_id = mpmbr_mp_id WHERE mpmbr_mbr_id = $id_membre


          Et attention dans ta table mp_mbr, tu as

          Citation

          KEY `mpmbr_mbr_id` (`mpmbr_mbr_id`,`mpmbr_mp_id`)


          Ca veut dire que t'as un index sur 2 colonnes, cad :
          - un where sur mpmbr_mbr_id utilise l'index
          - un where sur mpmbr_mbr_id ET (AND, pas OR) mpmbr_mp_id utilise l'index
          - un where sur mpmbr_mp_id ne peut pas utiliser l'index

          Je ne pense pas que ce soit vraiment ce que tu veux (impossible de récupérer tous les membres d'un sujet par exemple (enfin si possible, mais la requete n'utilisera pas l'index))
          • Partager sur Facebook
          • Partager sur Twitter
            1 mai 2006 à 11:00:40

            [winzou entre faire un CROSS JOIN puis filtrer les entrées et prendre directement les entrées correspondantes, c'est quoi le plus rapide ?]

            Et puis sur quoi tu te bases pour dire que c'est super lent ? :D ( ce qui est faux, c'est pas parce que sqlpro dit qu'il vaut mieux utiliser les jointures aux sous-requêtes que c'est vrai sur tous les SGBDR ;) )
            • Partager sur Facebook
            • Partager sur Twitter
              1 mai 2006 à 11:04:59

              En faite ce qu'il faut faire, c'est que je fais 2 requetes differentes, et je stocke chacune d'elles dans un array, et ensuite, je compare les 2 arrays etc pour afficher les info qu'il me faut ?

              shepard > personnellement, je prefere comme fait winzou :p
              • Partager sur Facebook
              • Partager sur Twitter
                1 mai 2006 à 11:06:12

                Shepard, sur des tests tout simplement :p

                J'avais testé sur je sais plus quelle table sur le sdz.
                Version sous requete : 8 secondes et quelques
                Version jointure : 0.01 seconde

                J'en ai conclut que j'utiliserai les jointures à présent :D

                (Même si sur la théorie je suis d'accord que ce résultat est surprenant, j'avais fait tout un speech pour dire le contraire, mais finalement en testant uhm :-°^^ )
                • Partager sur Facebook
                • Partager sur Twitter
                  1 mai 2006 à 11:44:30

                  hum, t'as du effectuer la version sous-requêtes une seule fois et la version jointures 35 fois :D^^ ( cache )

                  Enfin bon, ce résultat m'étonne franchement ^^

                  De toute façon, nous on n'aura plus ce problème avec les vues matérialisées :D:p
                  • Partager sur Facebook
                  • Partager sur Twitter
                    1 mai 2006 à 11:47:01

                    C'est quoi le vues materialisées :p ?

                    J'ai lu le lien que tu avais mis une fois, mais j'ai pas très très bien compris, moi et l'anglais :heu:

                    SInon, ça done quoi shepard la requete de barbare avec mysql >= 5.0 pour selection tous ce que je veux en une seule requetes :D ?
                    • Partager sur Facebook
                    • Partager sur Twitter
                      1 mai 2006 à 12:12:24

                      Avec MySQL >= 5.0 il aurait suffi de faire une fonction MySQL ( j'en parle quelque part dans mon tuto je crois ^^:D ) qui renverrait les ids / pseudos correspondant aux mp récupérés :)
                      • Partager sur Facebook
                      • Partager sur Twitter
                        1 mai 2006 à 12:27:54

                        A wé, c'est bien le truc de barbare :D
                        • Partager sur Facebook
                        • Partager sur Twitter
                          1 mai 2006 à 12:53:36

                          Ben non, moi je trouve ça joli d'avoir des fonctions persos dans les requêtes :p:)

                          Par contre la requête qui insert la nouvelle fonction, je veut bien admettre qu'elle ne soit pas des plus catholiques ^^:p
                          • Partager sur Facebook
                          • Partager sur Twitter
                            1 mai 2006 à 13:04:19

                            J'ai un petit probleme, j'ai compris comment faire ce que tu me dis, mais à un moment tu me dis de stocker les participants dans un tableau, mais sans utiliser mysql_fetch_xxxx.

                            Ok, mais comment recuperer ce tableau ?

                            Parce que mysql_query() return 0 ou 1.

                            Et pareil pour imploder tous les IDs. J'ai fait un fonction pour parce que avec implode(), ça marche pas :heu:.
                            Et à mon avis, il y'a moyen de mieux faire, beaucoup mieux :D
                            function implode_id(&$bdd)
                            {
                                    $ids = '';
                                   
                                    while($id = $bdd->return_row())
                                            $ids .= $id["mps_id"];
                                           
                                    return $ids;
                            }

                            $bdd->return_ro(), en faite ça return mysql_fetch_assoc(); :p
                            PS: elle separe pas encore les differents ID dans la chaine :D

                            Et derniere petite question, ça signifie quoi les <> dans la deuxieme requete :) ?
                            • Partager sur Facebook
                            • Partager sur Twitter
                              1 mai 2006 à 13:08:25

                              Non, tu dois utiliser une seule fois mysql_fetch_assoc pour mettre les données dans le tableau, puis tu ne dois recourir qu'à ce tableau, plus à de nouveaux mysql_fetch_assoc :)

                              while ( $tabdata[] = mysql_fetch_assoc($res) );

                              par exemple :)
                              • Partager sur Facebook
                              • Partager sur Twitter
                                1 mai 2006 à 13:10:46

                                Ha d'accord :)
                                C'est tout bête en faite :p

                                J'ai honte de pas avoir trouvé ça tout seul :heu:

                                Je vais essayer, et je vous tiens au courant :p

                                EDIT : voila ce que j'ai pu pondre :p

                                dites moi ce que vous en pensez

                                function list_sujet()
                                {
                                        $bdd = new database();
                                    $tpl = new templates("Autre");

                                        $tpl->open_template("mps", "squelette.tpl");
                                       
                                        cfg_mbr($bdd, "Messages privés", "Aucune");
                                        cfg_tpl($tpl, 'Templates/tpl/Style/news.tpl', 'Messages privés', 'Templates/tpl/Mp/FR/index.tpl');
                                       
                                        $get_mp = "SELECT mps_id, mps_titre, mps_last_id, mps_nb_vue, mps_nb_msg
                                                           FROM mp_mbr
                                                           LEFT JOIN mp_sujet ON mps_id = mpmbr_mp_id
                                                           WHERE mpmbr_mbr_id = "
                                .$_SESSION["mbr_id"];
                                                                                                                  
                                        $bdd->parse_query($get_mp);
                                       
                                        $sujets = set_tbldata($bdd);
                                       
                                        $mp_ids = implode_id($sujets);

                                        $get_participants = "SELECT mpmbr_mp_id, mpmbr_mbr_id, mbr_pseudo
                                                                                 FROM mp_mbr
                                                                                 LEFT JOIN membre ON mbr_id =  mpmbr_mbr_id
                                                                                 WHERE mpmbr_mp_id IN ($mp_ids)"
                                ;
                                                                                
                                        $bdd->parse_query($get_participants);
                                       
                                        $part_data = set_tbldata($bdd);
                                       
                                        foreach($sujets as $key => $value)
                                        {
                                                draw_participants($tpl, $part_data, $value["mps_id"]);
                                               
                                                $tpl->set_bloc_vars("liste_mp", array("mp_id" => $value["mps_id"],
                                                                                                                          "last_id" => $value["mps_last_id"],
                                                                                                                          "nb_vue" => $value["mps_nb_vue"],
                                                                                                                          "nb_msg" => $value["mps_nb_msg"]));
                                        }

                                        $tpl->draw_template("mps");
                                }

                                function implode_id(&$tbldata)
                                {
                                        $ids = '';
                                       
                                        foreach($tbldata as $key => $value)
                                        {
                                                if(empty($ids))
                                                        $ids .= $value["mps_id"];
                                                elseif(!empty($value["mps_id"]))
                                                        $ids .= "-".$value["mps_id"];
                                        }

                                        return $ids;
                                }

                                function set_tbldata(&$bdd)
                                {
                                        $tbldata = array();
                                       
                                        while($tbldata[] = $bdd->return_row());
                                       
                                        return $tbldata;
                                }

                                function draw_participants(&$tpl, $participants_data, $mp_id)
                                {
                                        foreach($participants_data as $key => $value)
                                        {
                                                if($value["mpmbr_mp_id"] == $mp_id)
                                                        $tpl->set_bloc_vars("part_sj".$value["mpmbr_mp_id"], array("mbr_id" => $value["mpmbr_mbr_id"],
                                                                                                                                                                  "mbr_pseudo" => $value["mbr_pseudo"]));
                                        }
                                }


                                Et surtout, s'il y a moyen d'optimiser tout ça :)
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  2 mai 2006 à 19:41:36

                                  Bon, suit à de multiple reflexion, j'en suis à cette requete pour lister les messaages privés.

                                  SELECT @mps_id := mps_id AS mps_id, mps_titre, mps_nb_vue, mps_nb_msg, COUNT(mplu_mps_id) AS lus, SELECT mpm_date FROM mp_msg WHERE mpm_id = @mps_id ORDER BY mpm_date DESC LIMIT 1) AS last_msg, (SELECT mpm_id FROM mp_msg WHERE mpm_id = @mps_id ORDER BY mpm_date DESC LIMIT 1) AS last_msg_id, FROM mp_mbr LEFT JOIN mp_sujet ON mps_id = mpmbr_mp_id LEFT JOIN mp_lus ON mplu_mps_id = mps_id AND mplu_mbr_id = $_SESSION["mbr_id"] WHERE mpmbr_mbr_id = $_SESSION["mbr_id"] AND mpmbr_mp_id = mps_id GROUP BY mps_id LIMIT $pagination['first_id'], $pagination['nb_items'];


                                  Mais le probleme, c'est qu'il ne veut pas de mes sous-requetes :(
                                  Si j'enleve mes sous-requetes, je n'ai pas d'erreur de syntaxe ;)

                                  Si quelqu'un pouvait m'aider, j'ai aucune idée, parce que à chaque fois que je fais une sous-requete, j'ai une erreur en plus :o

                                  Merci d'avance ;)
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    2 mai 2006 à 21:41:44

                                    Tu as quelle version de MySQL ??
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      2 mai 2006 à 22:25:31

                                      J'ai la version 4.0.24 ;)

                                      Heu, stp, dis moi que ma version accepte les sous-reqquetes :euh:
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        2 mai 2006 à 23:01:34

                                        4.1

                                        Mais c'est pas normal que tu fasse une requete comme ca :p
                                        Fais la technique que Shepard a dit au dessus, t'as besoin de juste 2 requetes assez simples
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          3 mai 2006 à 7:29:38

                                          Non, mais je fais la technique de shepard, et je dois dir que ça marche nickel et plutot rapide ;)

                                          Mais en faite, j'aimerai recuperer la date, l'id, et l'auteur du dernier message du MP.
                                          Or, ces informations sont dans une autre table ;) . Et comme j'ai vu dans un topic qu'il faisait des sous-requetes pour avoir ces informations, je fais pareil :p

                                          Sinon, me reste la possibilité de faire une 3° requete,mais je pense qu'on peut mieux faire (grace aux sous-requetes justement :p )

                                          Mais le probleme, c'est que j'ai une erreur de syntaxe dans ma requete, et que je ne vois pas ou :(

                                          en faite au debut j'avais un table mp_sujet comme ça :
                                          CREATE TABLE `mp_sujet`
                                          (
                                            `mps_id` smallint(3) UNSIGNED NOT NULL AUTO_INCREMENT,
                                            `mps_titre` varchar(255) NOT NULL DEFAULT '',
                                            `mps_auteur` smallint(4) UNSIGNED NOT NULL DEFAULT '0',
                                            `mps_nb_vue` smallint(3) UNSIGNED NOT NULL DEFAULT '0',
                                            `mps_nb_msg` smallint(3) UNSIGNED NOT NULL DEFAULT '0',
                                            `mps_last_id` smallint(2) UNSIGNED NOT NULL DEFAULT '0',
                                            PRIMARY KEY  (`mps_id`)
                                          ) TYPE=MyISAM COMMENT='Contient les sujets des mp' AUTO_INCREMENT=2 ;


                                          Et j'aurai rempli le chans mps_last_id lor de l'ajout d'un message, mais en voyant un autre topic avec un exemple de shepard et des table pas trop eloignées des miennes, j'ai corrigé comme ça :
                                          CREATE TABLE `mp_sujet`
                                          (
                                            `mps_id` smallint(3) UNSIGNED NOT NULL AUTO_INCREMENT,
                                            `mps_titre` varchar(255) NOT NULL DEFAULT '',
                                            `mps_nb_vue` smallint(3) UNSIGNED NOT NULL DEFAULT '0',
                                            `mps_nb_msg` smallint(3) UNSIGNED NOT NULL DEFAULT '0',
                                            PRIMARY KEY  (`mps_id`)
                                          ) TYPE=MyISAM COMMENT='Contient les sujets des mp' AUTO_INCREMENT=2 ;


                                          J'ai enlevé le chan mps_last_id, et le chan mps_pseudo.
                                          Sinon, mes autres tables restes les mêmes ;)
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            3 mai 2006 à 18:14:57

                                            Garde le mps_last_id, c'est la meilleur méthode (de loin)

                                            (et l'erreur de syntaxe vient de ta version de mysql qui n'accepte pas les sous requetes)
                                            • Partager sur Facebook
                                            • Partager sur Twitter

                                            System de MP à plusieur utilisateurs

                                            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                            × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                            • Editeur
                                            • Markdown