Partage
  • Partager sur Facebook
  • Partager sur Twitter

Jointure multiple

Sujet résolu
    29 mars 2020 à 0:25:11

    Bonjour à tous,

    J'ai 5 tables, a, b, c, d et e.

    De quelle manière peut-on faire une jointure entre b et c puis entre (b et c) et a sachant que toutes les autres tables ne sont liées qu'à a, dont c ?

    Pour l'instant j'ai ce code :

    SELECT a.a_info,
                b.b_info,
                c.c_info,
                d.d_info,
                e.e_info
    FROM a
    INNER JOIN b
    on a.b_id = b.id
    INNER JOIN c
    on a.c_id = c.id
    INNER JOIN d
    on a.d_id = d.id
    INNER JOIN e
    on a.e_id = e.id

    Merci d'avance pour votre réponse.

    -
    Edité par VincentLelong3 29 mars 2020 à 10:38:31

    • Partager sur Facebook
    • Partager sur Twitter
      29 mars 2020 à 12:16:29

      Bonjour, 

      Quelle est la structure de ces tables (colonnes) ?

      • Partager sur Facebook
      • Partager sur Twitter
      Seul on va plus vite, ensemble on va plus loin ... A maîtriser : Conception BDD, MySQL, PHP/MySQL
        29 mars 2020 à 12:30:44

           

        Voilà les tables (dans l'ordre, "used_e_cap_by_device", "used_e_cap", "new_e_cap" et "cap_series").

        Comme on peut le voir, il y a l'indication de la série ("cap_series_id") dans "used_e_cap_by_device" mais également dans "new_e_cap" qui est elle-même inclue dans "used_e_cap_by device.

        Et voilà le code actuel avec ces tables (où je n'ai pas le "cap_series_name" pour "new_e_cap") :

         $e_cap_req = $bdd->prepare('SELECT used_e_cap_by_device.used_e_cap_by_device_amount,
                                            used_e_cap.used_e_cap_capacitance,
                                            used_e_cap.used_e_cap_voltage,
                                            cap_series.cap_series_name,
                                            new_e_cap.new_e_cap_capacitance,
                                            new_e_cap.new_e_cap_voltage,
                                            new_e_cap.new_e_cap_resale_price
        FROM used_e_cap_by_device
        NATURAL JOIN used_e_cap
        NATURAL JOIN cap_series
        INNER JOIN new_e_cap
        on used_e_cap_by_device.new_e_cap_id = new_e_cap.new_e_cap_id
        WHERE device_id = :device_id 
        ORDER BY used_e_cap_capacitance, used_e_cap_voltage');
        $e_cap_req->execute(array('device_id' => $_GET['device_id']));

        -
        Edité par VincentLelong3 29 mars 2020 à 12:31:04

        • Partager sur Facebook
        • Partager sur Twitter
          29 mars 2020 à 15:20:44

          Bonjour,

          Déjà, je ne sais pas comment tu as généré ton modèle, mais ces noms de colonnes sont insupportables ... Reprendre le nom de la table dans le nom de la colonne c'est redondant et compliqué à réécrire ... Je ferai plutôt un truc comme ceci :

          Pour résoudre ton problème, si je l'ai bien compris, il te faut utiliser des alias (noms de remplacement) pour pouvoir utiliser plusieurs fois la même table dans ta requête ...

          La requête serait :

          SELECT
          	CD.used_e_cap_by_device_amount,
          	C.used_e_cap_capacitance,
          	C.used_e_cap_voltage,
          	CS1.cap_series_name,
          	NC.new_e_cap_capacitance,
          	NC.new_e_cap_voltage,
          	NC.new_e_cap_resale_price,
          	CS2.cap_series_name
          FROM
          	used_e_cap_by_device CD
          		INNER JOIN used_e_cap C
          			ON CD.used_e_cap_id = C.used_e_cap_id
          		INNER JOIN cap_series CS1
          			ON C.cap_series_id = CS1.cap_series_id
          		INNER JOIN new_e_cap NC
          			ON CD.new_e_cap_id = NC.new_e_cap_id
          		INNER JOIN cap_series CS2
          			ON NC.cap_series_id = CS2.cap_series_id
          WHERE CD.device_id = :device_id 
          ORDER BY C.used_e_cap_capacitance, C.used_e_cap_voltage

          Après, je ne vois pas l'intérêt de mettre cap_series_id dans la used_e_cap_by_device puisque tu le retrouves dans new_e_cap ...

          Sinon, peux-tu nous expliquer un peu ton projet ? Car j'ai l'impression que le modèle n'est pas terrible en l'état ...

          • Partager sur Facebook
          • Partager sur Twitter
          Seul on va plus vite, ensemble on va plus loin ... A maîtriser : Conception BDD, MySQL, PHP/MySQL
            29 mars 2020 à 15:38:05

            Voilà le diagramme des classes que moi j'avais fait :

            Sinon le but est d'afficher un tableau qui nous donne pour un appareil les anciens condensateurs et ceux que l'on utilise en remplacement.

            Le fait est que les séries utilisées varient d'un appareil à l'autre (d'où l'utilisation de la série dans "used_e_cap_by_device" et non dans "used_e_cap") alors que les séries utilisées en remplacement sont toujours les mêmes car l'atelier où je travaille et pour lequel je réalise cet outil ne stocke qu'une série par couple capacité-tension. (d'où le fait que les "new_e_cap" aient une série attribuée par valeur).

            Le résultat final avec l'affichage (j'ai un peu bidouillé pour qu'on puisse voir à quoi ça doit ressembler) :

            • Partager sur Facebook
            • Partager sur Twitter
              29 mars 2020 à 15:49:50

              Le MCD que tu as fais ne correspond pas au MLD que tu donnes après, pourquoi ne pas avoir conservés les noms ainsi :p

              La relation "Sont remplacés" est en fait incluse dans la relation "Contient".

              Quelle est la clé primaire de la table used_e_cap_by_device ?

              Sinon, la requête proposées juste avant, avec les alias, répond-elle à ton besoin ?

              -
              Edité par Benzouye 29 mars 2020 à 15:51:15

              • Partager sur Facebook
              • Partager sur Twitter
              Seul on va plus vite, ensemble on va plus loin ... A maîtriser : Conception BDD, MySQL, PHP/MySQL
                29 mars 2020 à 15:59:09

                La clé primaire de used_e_cap_by_device est (device_id, used_e_cap_id, cap_series_id).

                Pour les alias, il faut que j'essaye, ce qui m'inquiète c'est la façon de l'intégrer dans la suite du code, parce qu'actuellement j'avais ça :

                '<tr>
                     <td class=\'bd\'>' . $e_cap['used_e_cap_by_device_amount'] . '</td>
                     <td class=\'used\'>' . $e_cap['used_e_cap_capacitance'] . ' µF, ' . $e_cap['used_e_cap_voltage'] . ' V</td>
                     <td class=\'used\'>' . $e_cap['cap_series_name'] . '</td>
                     <td class=\'new\'>' . $e_cap['new_e_cap_capacitance'] . ' µF, ' . $e_cap['new_e_cap_voltage'] . ' V</td>
                     <td class=\'new\'> ??? </td>
                     <td class=\'bd\'>' . $e_cap['used_e_cap_by_device_amount']*$e_cap['new_e_cap_resale_price'] . ' €</td>
                </tr>';
                Or quand je mets "cap_series_name" dans la 5ème case de mon tableau, il se passe ça (ce qui n'est pas bon car ici je n'ai que les nouvelles séries, il ne m'a pris en compte que le deuxième des 2 join) :

                -
                Edité par VincentLelong3 29 mars 2020 à 16:27:40

                • Partager sur Facebook
                • Partager sur Twitter
                  30 mars 2020 à 14:02:15

                  Non, c'est parce que les deux colonnes ont le même nom, donc le même index dans le tableau PHP.

                  Là encore il faut utiliser des alias... exemple :

                  CS1.cap_series_name AS used_series,
                  NC.new_e_cap_capacitance,
                  NC.new_e_cap_voltage,
                  NC.new_e_cap_resale_price,
                  CS2.cap_series_name AS new_series

                  -
                  Edité par Benzouye 30 mars 2020 à 14:04:18

                  • Partager sur Facebook
                  • Partager sur Twitter
                  Seul on va plus vite, ensemble on va plus loin ... A maîtriser : Conception BDD, MySQL, PHP/MySQL
                    30 mars 2020 à 18:21:26

                    C'est exactement ce que j'avais fait, cela ne fonctionnait pas :(

                    Mais du coup j'ai trouvé une solution. C'est peut-être pas la meilleure pour l'instant mais elle a le mérite de fonctionner (désolé, j'ai pas encore mis d'alias ni changé le nom de mes variables mais pour l'instant avec ma faible expérience de code je me repère mieux):

                    $e_cap_req = $bdd->prepare('SELECT used_e_cap_by_device.used_e_cap_by_device_amount,
                                                       used_e_cap.used_e_cap_capacitance,
                                                       used_e_cap.used_e_cap_voltage,
                                                       cap_series.cap_series_name,
                                                       new_e_cap.new_e_cap_id,
                                                       new_e_cap.new_e_cap_capacitance,
                                                       new_e_cap.new_e_cap_voltage,
                                                       new_e_cap.new_e_cap_resale_price
                    FROM used_e_cap_by_device
                    NATURAL JOIN used_e_cap
                    NATURAL JOIN cap_series
                    INNER JOIN new_e_cap
                    on used_e_cap_by_device.new_e_cap_id = new_e_cap.new_e_cap_id
                    WHERE device_id = :device_id 
                    ORDER BY used_e_cap_capacitance, used_e_cap_voltage');

                    $e_cap_req->execute(array('device_id' => htmlspecialchars($_GET['device_id'])));

                    $e_cap_total_price = 0;
                    while ($e_cap = $e_cap_req->fetch())
                    {
                        $new_series_req = $bdd->prepare('SELECT cap_series.cap_series_name
                        FROM new_e_cap
                        NATURAL JOIN cap_series
                        WHERE new_e_cap.new_e_cap_id = :new_e_cap_id');
                        $new_series_req->execute(array('new_e_cap_id' => $e_cap['new_e_cap_id']));

                        $new_series = $new_series_req->fetch();

                        echo 
                            '<tr>
                        <td class=\'bd\'>' . $e_cap['used_e_cap_by_device_amount'] . '</td>
                         <td class=\'used\'>' . $e_cap['used_e_cap_capacitance'] . ' µF, ' . $e_cap['used_e_cap_voltage'] . ' V</td>
                        <td class=\'used\'>' . $e_cap['cap_series_name'] . '</td>
                         <td class=\'new\'>' . $e_cap['new_e_cap_capacitance'] . ' µF, ' . $e_cap['new_e_cap_voltage'] . ' V</td>
                         <td class=\'new\'>' . $new_series['cap_series_name'] . '</td>
                         <td class=\'bd\'>' . $e_cap['used_e_cap_by_device_amount']*$e_cap['new_e_cap_resale_price'] . ' €</td>
                         </tr>';
                        $e_cap_total_price = $e_cap_total_price + $e_cap['used_e_cap_by_device_amount']*$e_cap['new_e_cap_resale_price'];
                    }

                    $e_cap_req->closeCursor();
                    • Partager sur Facebook
                    • Partager sur Twitter
                      30 mars 2020 à 18:36:11

                      Ne jamais faire de requête à l'intérieur d'une boucle ... C'est un coup à mettre ton serveur à genou ...

                      Ce code devrait fonctionner :

                      <?php
                      	$e_cap_req = $bdd->prepare('
                      		SELECT
                      			CD.used_e_cap_by_device_amount,
                      			C.used_e_cap_capacitance,
                      			C.used_e_cap_voltage,
                      			CS1.cap_series_name AS used_series,
                      			NC.new_e_cap_id,
                      			NC.new_e_cap_capacitance,
                      			NC.new_e_cap_voltage,
                      			NC.new_e_cap_resale_price,
                      			CS2.cap_series_name AS new_series
                      		FROM
                      			used_e_cap_by_device CD
                      				INNER JOIN used_e_cap C
                      					ON CD.used_e_cap_id = C.used_e_cap_id
                      				INNER JOIN cap_series CS1
                      					ON C.cap_series_id = CS1.cap_series_id
                      				INNER JOIN new_e_cap NC
                      					ON CD.new_e_cap_id = NC.new_e_cap_id
                      				INNER JOIN cap_series CS2
                      					ON NC.cap_series_id = CS2.cap_series_id
                      		WHERE CD.device_id = :device_id
                      		ORDER BY C.used_e_cap_capacitance, C.used_e_cap_voltage'
                      	);
                      	$e_cap_req->execute( array( 'device_id' => $_GET['device_id'] ) );
                      	$e_cap_total_price = 0;
                      	while( $e_cap = $e_cap_req->fetch() ) {
                      ?>
                      	<tr>
                      		<td class="bd"><?php echo $e_cap['used_e_cap_by_device_amount']; ?></td>
                      		<td class="used"><?php echo $e_cap['used_e_cap_capacitance']; ?> µF, <?php echo $e_cap['used_e_cap_voltage']; ?> V</td>
                      		<td class="used"><?php echo $e_cap['used_series']; ?></td>
                      		<td class="new"><?php echo $e_cap['new_e_cap_capacitance']; ?> µF, <?php echo $e_cap['new_e_cap_voltage']; ?> V</td>
                      		<td class="new"><?php echo $e_cap['new_series']; ?></td>
                      		<td class="bd"><?php echo $e_cap['used_e_cap_by_device_amount']*$e_cap['new_e_cap_resale_price']; ?> €</td>
                      	</tr>
                      <?php
                      		$e_cap_total_price = $e_cap_total_price + $e_cap['used_e_cap_by_device_amount']*$e_cap['new_e_cap_resale_price'];
                      	}
                      	$e_cap_req->closeCursor();
                      ?>
                      • Partager sur Facebook
                      • Partager sur Twitter
                      Seul on va plus vite, ensemble on va plus loin ... A maîtriser : Conception BDD, MySQL, PHP/MySQL
                        30 mars 2020 à 22:46:03

                        J'avais déjà essayé cette version aussi et je te confirme le fait que ça marche pas avec le code erreur :

                        • Partager sur Facebook
                        • Partager sur Twitter
                          31 mars 2020 à 0:38:47

                          Regarde l'erreur... c'est juste une faute de frappe ... remplace le C par CD dans la clause ON de la jointure avec la table series CS1 ...

                          • Partager sur Facebook
                          • Partager sur Twitter
                          Seul on va plus vite, ensemble on va plus loin ... A maîtriser : Conception BDD, MySQL, PHP/MySQL
                            31 mars 2020 à 8:52:11

                            Ah oui mea culpa, merci beaucoup, c'est pour ça que pour l'instant je préférai garder mes noms à rallonge, ça me parle plus à la relecture ou en cas de problème ;)

                            Ça marche a priori, maerci beaucoup.

                            Je vais essayer de corriger les tables pour lesquelles j'avais des requêtes dans les boucle mais normalement tout devrait marcher sur le programme normalement.

                            Encore merci et bonne journée à toi !

                            • Partager sur Facebook
                            • Partager sur Twitter

                            Jointure multiple

                            × 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