Partage
  • Partager sur Facebook
  • Partager sur Twitter

Problème de résultat sur une Requete SQL

Full join et left join

Sujet résolu
    20 mai 2019 à 11:41:46

    Bonjour,

    Pourriez-vous m'aider s'il vous plaît?

    Ma 1ère requête ne retourne pas un nombre suffisant de résultat (il manque des MEDIA) et ma 2nde requête n'intègre pas les 2 tables nécessaires à mon résultat final.

    Je souhaiterais comprendre comment je dois faire en sachant que si pour un MEDIA il n'y a pas de commande je veux une ligne avec des 0 ou null.

    1er req:

    SELECT MEDIA,  MEDLibel, MEDDATE, MEDDTCDE, MEDCDE,
    VPCMED, SUM( VPCCDE) AS TOT_CDE FROM  TableMedia
    FULL JOIN  VPCMEDIA ON TableMedia.MEDIA = VPCMEDIA.VPCMED   
    WHERE MEDDATE BETWEEN '20180517' AND '20190517'
    AND MEDDTCDE BETWEEN '20180517' AND '20190517'
    AND VPCDAT BETWEEN '20190501' AND '20190517'
    AND VPCMDR <> 'CB'    
    GROUP BY VPCMED, MEDIA,  MEDLibel, MEDDATE, MEDDTCDE, MEDCDE
    ORDER BY TableMedia.MEDIA 

    2e req:

    SELECT MEDIA, MEDLibel, MEDDATE, MEDDTCDE, MEDCDE
    FROM  TableMedia 
    WHERE MEDDATE BETWEEN '20180517' AND '20190517'
    AND MEDDTCDE BETWEEN '20180517' AND '20190517'
    ORDER BY MEDIA 

    NB : Sur ma 1ère requête quelque soit la jointure j'ai le même résultat (left join ou full join)

    Merci d'avance pour vos réponses.

    • Partager sur Facebook
    • Partager sur Twitter
      20 mai 2019 à 12:00:09

      Bonjour,

      RamCif a écrit:

      si pour un MEDIA il n'y a pas de commande je veux une ligne avec des 0 ou null

      C'est le principe des jointures externes (LEFT ou RIGHT JOIN).

      Sauf que pour que la jointure externe soit efficace tu ne dois pas poser de condition sur les colonnes de la table "facultative" dans ta clause WHERE.

      Peux-tu nous préciser la structure des deux tables en jeu dans ta requête ? Où se trouve chacune des colonnes mentionnées ?

      • Partager sur Facebook
      • Partager sur Twitter
      Seul on va plus vite, ensemble on va plus loin ... A maîtriser : Conception BDD, MySQL, PHP/MySQL
        20 mai 2019 à 14:39:02

        Bonjour Benzouye et merci pour ton aide.

        TableMedia :

        MEDIA : Clé unique

        MEDLibel : Libellé du média

        MEDDATE : Date de création

        MEDDTCDE : Date de la dernière commande

        MEDCDE : Somme du nombre totale de commande depuis sa création (ne varie pas dans le temps sauf si il y a une nouvelle commande qui s'y rajoute)

        VPCMédia:

        VPCMED : Réf du média (identique à MEDIA)

        VPCCDE : Nombre de commande de ce média d'où l'intérêt de faire SUM( VPCCDE) sur une période d'achat

        VPCDAT : Date d'achat

        VPCMDR: Moyen de règlement

        La 1ère requête retourne la liste de tous les média créé et vendu sur l'année flottante (par l'exemple on va dire qu'elle en a 1000)

        La seconde requête retourne  le nombre de commande des médias sur le mois en cours mais en se basant sur la liste de l'année flottante.

        Le résultats est bon mais elle ne retourne que la liste des médias où il y a eu au moins une commande et ne retourne pas ceux sans mouvements (on va dire qu'elle ne retourne que 800 médias car 200 n'ont pas du tout étaient vendus). C'est comme si j'avais fait une jointure classique avec le where entre 2 tables.

        • Partager sur Facebook
        • Partager sur Twitter
          20 mai 2019 à 15:03:02

          Ok,

          Donc en utilisant une jointure gauche, soit tu sors les conditions de la table VPC de la clause WHERE pour les mettre dans la jointure :

          SELECT
              M.MEDIA,
              M.MEDLibel,
              M.MEDDATE,
              M.MEDDTCDE,
              M.MEDCDE,
              V.VPCMED,
              SUM( V.VPCCDE ) AS TOT_CDE
          FROM
              TableMedia M
                  LEFT JOIN VPCMEDIA V
                      ON M.MEDIA = V.VPCMED
                      AND V.VPCDAT BETWEEN '20190501' AND '20190517'
                      AND V.VPCMDR <> 'CB'
          WHERE
              M.MEDDATE BETWEEN '20180517' AND '20190517'
              AND M.MEDDTCDE BETWEEN '20180517' AND '20190517'
          GROUP BY
              M.MEDIA,
              M.MEDLibel,
              M.MEDDATE,
              M.MEDDTCDE,
              M.MEDCDE,
              V.VPCMED
          ORDER BY MEDIA

          Soit tu ajoutes une condition IS NULL :

          SELECT
              M.MEDIA,
              M.MEDLibel,
              M.MEDDATE,
              M.MEDDTCDE,
              M.MEDCDE,
              V.VPCMED,
              SUM( V.VPCCDE ) AS TOT_CDE
          FROM
              TableMedia M
                  LEFT JOIN VPCMEDIA V
                      ON M.MEDIA = V.VPCMED
          WHERE
              M.MEDDATE BETWEEN '20180517' AND '20190517'
              AND M.MEDDTCDE BETWEEN '20180517' AND '20190517'
              AND (
                  V.VPCDAT BETWEEN '20190501' AND '20190517'
                  AND V.VPCMDR <> 'CB'
                  OR V.VPCMED IS NULL
              )
          GROUP BY
              M.MEDIA,
              M.MEDLibel,
              M.MEDDATE,
              M.MEDDTCDE,
              M.MEDCDE,
              V.VPCMED
          ORDER BY MEDIA

          Je préfères la première, plus lisible ...

          -
          Edité par Benzouye 20 mai 2019 à 15:03:41

          • Partager sur Facebook
          • Partager sur Twitter
          Seul on va plus vite, ensemble on va plus loin ... A maîtriser : Conception BDD, MySQL, PHP/MySQL
            20 mai 2019 à 15:28:25

            UN grand merci Benzouye :-)) , je n'avais pas bien compris le fonctionnement de cette jointure et en mettant les conditions comme tu l'as fait au bonne endroit tous les enregistrements sont bien là. Si je peux abuser encore un peu de tes compétences.

            Je souhaiterais avoir une seconde colonne qui me permette d'avoir VPCMED avec le nombre de commande sur une période d'1an et sur 1mois comment je dois les imbrider?

            Merci d'avance.

            -
            Edité par RamCif 20 mai 2019 à 15:45:06

            • Partager sur Facebook
            • Partager sur Twitter
              20 mai 2019 à 15:46:54

              RamCif a écrit:

              avoir une seconde colonne qui me permette d'avoir VPCMED sur 1an et sur 1mois

              Je ne comprends pas ? Cela représente 2 requêtes différentes ...

              Si tu veux tout afficher en même temps ... Il faut deux sous-requêtes :

              SELECT
                  M.MEDIA,
                  M.MEDLibel,
                  M.MEDDATE,
                  M.MEDDTCDE,
                  M.MEDCDE,
                  V.VPCMED,
                  COALESCE( VM.total, 0 ) AS VPCMOIS,
                  COALESCE( VA.total, 0 ) AS VPCAN
              FROM
                  TableMedia M
                      LEFT JOIN (
                              -- VPC non CB mai 2019
                              SELECT VPCMED, SUM( VPCCDE ) AS total
                              FROM VPCMEDIA
                              WHERE
                                  V.VPCDAT BETWEEN '20190501' AND '20190517'
                                  AND V.VPCMDR <> 'CB'
                          ) VM
                          ON M.MEDIA = VM.VPCMED
                      LEFT JOIN (
                              -- VPC non CB 2019
                              SELECT VPCMED, SUM( VPCCDE ) AS total
                              FROM VPCMEDIA
                              WHERE
                                  V.VPCDAT BETWEEN '20190101' AND '20190517'
                                  AND V.VPCMDR <> 'CB'
                          ) VA
                          ON M.MEDIA = VA.VPCMED

              Et une clause WHERE sur les dates de la table MEDIA ... A définir ...

              • Partager sur Facebook
              • Partager sur Twitter
              Seul on va plus vite, ensemble on va plus loin ... A maîtriser : Conception BDD, MySQL, PHP/MySQL
                20 mai 2019 à 16:38:36

                Ça pique les yeux, j'aurais pu chercher longtemps sans trouver ce genre de code.

                Ce code "COALESCE" : je n'ai jamais vu ça ailleurs.

                Par contre je n'arrive pas à le faire fonctionner c'est trop compliqué pour moi : il ne reconnait pas le VPCMED :-/

                -
                Edité par RamCif 20 mai 2019 à 16:38:56

                • Partager sur Facebook
                • Partager sur Twitter
                  20 mai 2019 à 16:57:20

                  RamCif a écrit:

                  il ne reconnait pas le VPCMED

                  Oui, c'est ma faute ... V.VPCMED n'existe plus dans cette requête ... et j'avais oublié le GROUP BY dans les sous-requêtes ...

                  RamCif a écrit:

                  "COALESCE" : je n'ai jamais vu ça ailleurs.

                  Cette fonction retourne la première valeur non nulle de la liste de paramètres passés.

                  Du coup, la correction serait :

                  SELECT
                      M.MEDIA,
                      M.MEDLibel,
                      M.MEDDATE,
                      M.MEDDTCDE,
                      M.MEDCDE,
                      COALESCE( VM.VPCMED, VA.VPCMED, 'Aucune vente' ) AS VPCMED
                      COALESCE( VM.total, 0 ) AS VPCMOIS,
                      COALESCE( VA.total, 0 ) AS VPCAN
                  FROM
                      TableMedia M
                          LEFT JOIN (
                                  -- VPC non CB mai 2019
                                  SELECT VPCMED, SUM( VPCCDE ) AS total
                                  FROM VPCMEDIA
                                  WHERE
                                      V.VPCDAT BETWEEN '20190501' AND '20190531'
                                      AND V.VPCMDR <> 'CB'
                                  GROUP BY VPCMED
                              ) VM
                              ON M.MEDIA = VM.VPCMED
                          LEFT JOIN (
                                  -- VPC non CB 2019
                                  SELECT VPCMED, SUM( VPCCDE ) AS total
                                  FROM VPCMEDIA
                                  WHERE
                                      V.VPCDAT BETWEEN '20190101' AND '20191231'
                                      AND V.VPCMDR <> 'CB'
                                  GROUP BY VPCMED
                              ) VA
                              ON M.MEDIA = VA.VPCMED

                  -
                  Edité par Benzouye 20 mai 2019 à 16:58:01

                  • Partager sur Facebook
                  • Partager sur Twitter
                  Seul on va plus vite, ensemble on va plus loin ... A maîtriser : Conception BDD, MySQL, PHP/MySQL
                    20 mai 2019 à 17:00:13

                    Un très grand merci Benzouye, je testerai demain. Bonne soirée.
                    • Partager sur Facebook
                    • Partager sur Twitter
                      20 mai 2019 à 17:05:41

                      De rien, à demain :p

                      • Partager sur Facebook
                      • Partager sur Twitter
                      Seul on va plus vite, ensemble on va plus loin ... A maîtriser : Conception BDD, MySQL, PHP/MySQL
                        21 mai 2019 à 15:36:31

                        Bonjour Benzouye,

                        J'ai testé la requête sur mon poste, elle marche nickel :D tu es trop fort :magicien:

                        J'y ai rajouté plein de condition et elle est super rapide à s'exécuter contrairement aux anciennes requêtes utilisés par le programme d'origine.

                        Mille merci pour ton aide précieuse et peut-être à une prochaine.

                        -
                        Edité par RamCif 21 mai 2019 à 15:37:33

                        • Partager sur Facebook
                        • Partager sur Twitter

                        Problème de résultat sur une Requete SQL

                        × 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