Partage
  • Partager sur Facebook
  • Partager sur Twitter

MySQL Somme Cumulée + Somme Cumulée + Group By

Sujet résolu
    19 novembre 2020 à 17:23:08

    Bonjour, 

    J'ai quelques difficulté à faire une requête

    Contexte : 

    J'ai une table evenement (je doit faire une somme cumulée des durees avec le code 'T5' * 0.5) par date

    J'ai une Table element (je doit faire une somme cumulée des cout element * Quantite) par date

    exemple avec la table Element (c'est le même principe pour evenement): 

    Saisie 1 : cout_element : 10 , Quantite : 3,   Date : 01/01 

    Saisie 2 : Cout_element : 5,  Quantite : 2, Date : 01/01

    ==> date : 01/01 , resultat : 10 * 3 + 5 * 2 ...

     Ici j'ai fait : (je pense qui doit y avoir une meilleur solution) 

    SELECT (a.valeur1 + b.valeur2) as resultat From table1
    LEFT JOIN(SELECT id, SUM(evenement.duree * 0.5) as valeur1 FROM evenement GROUP BY evenement.date) a ON table1.id = a.id
    LEFT JOIN(SELECT id, SUM(element*cout * element.quantite) as valeur2 FROM element GROUP BY element.date) b ON table1.id = b.id

    mais la ou ça se complique c'est que j'ai besoin de faire un deuxième cumule de l'ensemble par date.   

    Exemple :

    date : 01/01, resultat : 40

    date : 02/01, resultat: 20

    DONC le 02/01 j'aimerai avoir un résultat 60

    ...

    J'ai essayé avec une variable que j'incrémente

    SET @SumVal := 0
    SELECT @SumVal := @SumVal + (a.valeur1 + b.valeur2) as resultat From table1
    LEFT JOIN(SELECT id, SUM(evenement.duree * 0.5) as valeur1 FROM evenement GROUP BY evenement.date) a ON table1.id = a.id
    LEFT JOIN(SELECT id, SUM(element*cout * element.quantite) as valeur2 FROM element GROUP BY element.date) b ON table1.id = b.id

    Le problème c'est mon GOUP BY car j'ai l'impression qu'il lit quand même toutes les lignes : 

    si je fait @SumVal := @SumVal + 1 ==> à la deuxième ligne il me ressort un SumVal à 13 ? 

    Edit: la solution serait peut-être de subdivisé encore la chose : 

    SET @SumVal := 0
    SELECT @SumVal := @SumVal + resultat From (SELECT (a.valeur1 + b.valeur2) as resultat FROM table1
    LEFT JOIN(SELECT id, SUM(evenement.duree * 0.5) as valeur1 FROM evenement GROUP BY evenement.date) a ON table1.id = a.id LEFT JOIN(SELECT id, SUM(element*cout * element.quantite) as valeur2 FROM element GROUP BY element.date) b ON table1.id = b.id)


    je vais essayé demain, mais je suis pas sûr que c'est concluant, car j'aurai toujours le problème du GROUP BY ? 

    Peut être faire un count du nombre de ligne ... ? 

     Je vous remercie pour votre aide

    -
    Edité par DeveloSt 19 novembre 2020 à 17:42:22

    • Partager sur Facebook
    • Partager sur Twitter

    Site Internet : https://devst.go.yj.fr

      19 novembre 2020 à 17:43:07

      Bonjour,

      Avant même de regarder le cumul, dans tes sous-requête tu fais des GROUP BY date, mais tu mets id dans le SELECT ... pas glop ...

      As-tu juste regardé ce que retourne chaque sous-requête ?

      Tu veux regrouper par date ou par id ?

      Par ailleurs, j'imagine que le code donné n'est pas le code utilisé ... Peux-tu nous donner le code réellement utilisé ?

      • Partager sur Facebook
      • Partager sur Twitter
      Seul on va plus vite, ensemble on va plus loin ... A maîtriser : Conception BDD, MySQL, PHP/MySQL
        19 novembre 2020 à 18:17:15

        Benzouye a écrit:

        As-tu juste regardé ce que retourne chaque sous-requête ?


        Oui les sous requête me donne bien le bon résultat pour la table element et la table evenement. 

        Benzouye a écrit:

        Tu veux regrouper par date ou par id ?

        Bonne question ? Dans l'application j'ai un tableau ou je regroupe par id du secteur sur une plage de duree (fonctionne car j'ai pas besoin segmenter par date) je fait une somme cumule de dateDebut à datefIN => j'utilise le WHERE

        Mais pour le graphe (c'est l'inverse) c'est bien par date et avec un dropDown garder la possibilité de changer de secteur.  :)  (Or ici j'ai besoin de faire la somme cumulee pour chaque dates) => je doit utiliser le GROUP BY

        Benzouye a écrit:

        Avant même de regarder le cumul, dans tes sous-requête tu fais des GROUP BY date, mais tu mets id dans le SELECT ... pas glop ...

        Oui j'ai du me mélanger un peu les pinceaux. Il commence a se faire tard 😅

        Benzouye a écrit:

        Par ailleurs, j'imagine que le code donné n'est pas le code utilisé ... Peux-tu nous donner le code réellement utilisé ?


        Je regarde pour le poster demain

        -
        Edité par DeveloSt 19 novembre 2020 à 18:28:32

        • Partager sur Facebook
        • Partager sur Twitter

        Site Internet : https://devst.go.yj.fr

          19 novembre 2020 à 18:32:09

          DeveloSt a écrit:

          les sous requête me donne bien le bon résultat pour la table element et la table evenement

          Je ne vois pas comment cela serait possible puisque tu n'y retournes pas la date, et que tu ne tries même pas par la date ... tu as des id qui se suivent avec des sommes sans date et parfois plusieurs fois le même id du coup ... Non vraiment ce n'est pas possible ...

          DeveloSt a écrit:

          Bonne question ? Dans l'application j'ai un tableau ou je regroupe par id du secteur sur une plage de duree (fonctionne car j'ai pas besoin segmenter par date) je fait une somme cumule de dateDebut à datefIN => j'utilise le WHERE

          Mais pour le graphe (c'est l'inverse) c'est bien par date et avec un dropDown garder la possibilité de changer de secteur.  :)  (Or ici j'ai besoin de faire la somme cumulee pour chaque dates) => je doit utiliser le GROUP BY

          Encore une fois, je n'arrive pas à comprendre ce que tu cherches à faire, et avec quel type de données tu travailles ... C'est pour cela que j'avais arrêté de répondre sur ton autre sujet, je devenais dingue de ne pas comprendre :D

          Peux-tu nous donner un exemple complet de données, et le résultat que tu attendrais avec celles-ci ?

          -
          Edité par Benzouye 19 novembre 2020 à 18:33:00

          • Partager sur Facebook
          • Partager sur Twitter
          Seul on va plus vite, ensemble on va plus loin ... A maîtriser : Conception BDD, MySQL, PHP/MySQL
            19 novembre 2020 à 20:11:00

            Benzouye a écrit:

            Encore une fois, je n'arrive pas à comprendre ce que tu cherches à faire, et avec quel type de données tu travailles ... C'est pour cela que j'avais arrêté de répondre sur ton autre sujet, je devenais dingue de ne pas comprendre :D

            Peux-tu nous donner un exemple complet de données, et le résultat que tu attendrais avec celles-ci ?

            -
            Edité par Benzouye il y a environ 1 heure


            C'est vrai que c'est pas très simple a visualiser : (L'Affichage Tableau j'ai réussi à le faire c'est plutôt le graphe qui me pose problème)

            Je poste cette image (Evenement(Code c'est partout T5) Excel me l'a incrémenté, j'ai pas fait attention) : 

            -
            Edité par DeveloSt 19 novembre 2020 à 20:15:15

            • Partager sur Facebook
            • Partager sur Twitter

            Site Internet : https://devst.go.yj.fr

              19 novembre 2020 à 21:08:29

              Pour calculer le coût 1, c'est simple :

              SELECT
              	EV.date,
              	EV.secteur,
              	SUM( EV.duree * 0.5 ) AS cout1
              FROM evenement EV
              GROUP BY
              	EV.date,
              	EV.id_secteur;

              Pour calculer le coût 2, c'est aussi simple, mais avec plus de jointures :

              SELECT
              	EV.date,
              	EV.id_secteur,
              	SUM( E.cout * C.quantite ) AS cout2
              FROM
              	evenement EV
              		INNER JOIN Element_Secteur ES
              			ON EV.id_secteur = ES.id_secteur
              		INNER JOIN Element E
              			ON ES.id_element = E.id_element
              		INNER JOIN Cout C
              			ON ES.id_element = C.id_element
              			AND ES.id_secteur = C.id_secteur
              GROUP BY
              	EV.date,
              	EV.id_secteur;

              Ce n'est pas vraiment ce que tu as fais précédemment ... Je ne comprends pas comment cela pouvait fonctionner ...

              Pour regrouper ces données et construire ton tableau cela donne un truc ... lourd :

              SELECT
              	D.date,
              	S.id_secteur,
              	S.NomSecteur,
              	COALESCE( C1.cout1, 0 ) AS cout1,
              	COALESCE( C2.cout2, 0 ) AS cout2,
              	COALESCE( C1.cout1, 0 ) + COALESCE( C2.cout2, 0 ) AS total
              FROM
              	(
              		-- Liste des dates possibles
              		SELECT DISTINCT date
              		FROM evenement
              	) D
              		
              		CROSS JOIN secteur S
              		
              		LEFT JOIN (
              				-- Calcul du coût 1
              				SELECT
              					EV.date,
              					EV.secteur,
              					SUM( EV.duree * 0.5 ) AS cout1
              				FROM evenement EV
              				GROUP BY
              					EV.date,
              					EV.id_secteur
              			) C1
              			ON D.date = C1.date
              			AND S.id_secteur = C1.id_secteur
              		
              		LEFT JOIN (
              				-- Calcul du coût 2
              				SELECT
              					EV.date,
              					EV.id_secteur,
              					SUM( E.cout * C.quantite ) AS cout2
              				FROM
              					evenement EV
              						INNER JOIN Element_Secteur ES
              							ON EV.id_secteur = ES.id_secteur
              						INNER JOIN Element E
              							ON ES.id_element = E.id_element
              						INNER JOIN Cout C
              							ON ES.id_element = C.id_element
              							AND ES.id_secteur = C.id_secteur
              				GROUP BY
              					EV.date,
              					EV.id_secteur
              			) C1
              			ON D.date = C1.date
              			AND S.id_secteur = C1.id_secteur
              
              ORDER BY D.date, S.id_secteur

              Maintenant, pour faire ton graphe, qui puisse faire à la fois tous les secteurs ou un secteur particulier ... bah il faudrait 2 requêtes je pense ...

              Pour un secteur donné :

              SELECT
              	D.date,
              	SUM( C1.cout1 ) + SUM( C2.cout2 ) AS total,
              	@cumul := @cumul + SUM( C1.cout1 ) + SUM( C2.cout2 ) AS cumul
              FROM
              	( SELECT @cumul:=0 ) T,
              	(
              		-- Liste des dates possibles
              		SELECT DISTINCT date
              		FROM evenement
              	) D
              		LEFT JOIN (
              				-- Calcul du coût 1
              				SELECT
              					EV.date,
              					SUM( EV.duree * 0.5 ) AS cout1
              				FROM evenement EV
              				WHERE EV.id_secteur = '...'
              				GROUP BY EV.date
              			) C1
              			ON D.date = C1.date
              		
              		LEFT JOIN (
              				-- Calcul du coût 2
              				SELECT
              					EV.date,
              					SUM( E.cout * C.quantite ) AS cout2
              				FROM
              					evenement EV
              						INNER JOIN Element_Secteur ES
              							ON EV.id_secteur = ES.id_secteur
              						INNER JOIN Element E
              							ON ES.id_element = E.id_element
              						INNER JOIN Cout C
              							ON ES.id_element = C.id_element
              							AND ES.id_secteur = C.id_secteur
              				WHERE EV.id_secteur = '...'
              				GROUP BY EV.date
              			) C1
              			ON D.date = C1.date
              
              GROUP BY D.date
              ORDER BY D.date

              Pour tous les secteurs, il faut retirer la clause WHERE dans les sous-requêtes.

              • 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 novembre 2020 à 8:28:40

                Merci beaucoup Benzouye pour le temps que tu as passé, 

                oui les 2 premières sont simple :) 

                Un exemple avec les données suivantes :

                Table Cout : 

                Table Element (exemple) : (il y a plus de 10 000 elements...)

                Table Evenement : 

                Pour la troisième requête je fait ça : 

                SELECT secteur.id_secteur, ROUND((event.duree * 0.5),1) AS cout1, ROUND((elt.cnq_pc),1) AS cout2, ROUND((event.duree * 0.5 + elt.cnq_pc),1) AS cout_tot
                FROM lds.id_secteur
                
                LEFT JOIN (
                SELECT evenement.id_secteur, SUM(CASE WHEN evenement.typeEvenement = 'T5' THEN evenement.duree ELSE 0 END) AS duree FROM lds.evenement 
                WHERE evenement.date BETWEEN '2020-11-05' AND '2020-11-20' 
                GROUP BY evenement.id_secteur) 
                event ON secteur.id_secteur = event.secteur
                
                LEFT JOIN (
                SELECT cout.id_secteur, SUM(cout.quantite * element.Cout) AS cnq_pc FROM lds.cout 
                LEFT JOIN lds.element ON cout.id_Element = element.id_Element 
                WHERE DATE(cout.DateHeure) BETWEEN '2020-11-05' AND '2020-11-20' 
                GROUP BY cout.id_secteur)
                elt ON secteur.id_secteur = elt.id_secteur 
                
                LEFT JOIN lds.cout ON secteur.id_secteur = cout.id_secteur
                LEFT JOIN lds.element ON cout.id_Element = element.id_Element
                LEFT JOIN lds.produit ON secteur.id_secteur = produit.id_secteur
                WHERE DATE(cout.DateHeure) BETWEEN '2020-11-05' AND '2020-11-20'
                GROUP BY secteur.id_secteur



                j'obtient : (ce qui est cohérent avec ce que je recherche)

                Je regarderais de plus prés comment tu réalise cette partie cette après midi :) 

                J'avais hésité a repartir des 2 premières faire le calcul en vb puis construire mon tableau. 

                L'application de manière générale est séparé en 4 parties (Saisie/Affichage, consolidation, configuration et administration) 

                Comme je suis entrain de faire la consolidation et que ce n'est que de la visu de donnée normalement (tableau/graphique) pas de INSERT INTO ou UPDATE que des SELECT, aucune interaction avec utilisateur (sauf : choix secteur/choix date) j'ai pas envie de m'embêter avec du VB. 

                La ou je bloque c'est pour le graphique (Je vais essayer ton code) 

                Pour les sous requetes j'ai un peu de mal a voir dans quelle cas tu fait :  

                 

                SELECT ... FROM table LEFT JOIN(SELECT ... ) 

                 

                ou  

                 

                SELECT ... FROM (SELECT ... FROM LEFT JOIN (SELECT ... )  

                EDIT : Pour ta Quatrieme requêtes c'est possible de passer par un like '%'

                -
                Edité par DeveloSt 20 novembre 2020 à 9:28:01

                • Partager sur Facebook
                • Partager sur Twitter

                Site Internet : https://devst.go.yj.fr

                  20 novembre 2020 à 9:40:02

                  DeveloSt a écrit:

                  Pour ta Quatrieme requêtes c'est possible de passer par un like '%'

                  Oui, ce sera juste moins rapide ...

                  • 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 novembre 2020 à 10:39:54

                    Tu veux dire que c'est mieux de faire

                    if secteur = "%" Then 

                    String = ""

                    else

                    String = "WHERE = 'secteur'"

                    end if

                    Requete + String

                    Du coup je l'utilise 4-5 fois ailleurs (le LIKE '%') 

                    Après ça me dérange pas trop car dans l'affichage car j'exécute uniquement les requête qui sont demandé (tableau graphique)

                    -
                    Edité par DeveloSt 20 novembre 2020 à 10:42:48

                    • Partager sur Facebook
                    • Partager sur Twitter

                    Site Internet : https://devst.go.yj.fr

                      20 novembre 2020 à 10:51:25

                      WHERE secteur LIKE '%'

                      Sera toujours plus lent que rien du tout, mais si ton volume de données n'est pas énorme, ce sera insensible ...

                      Si tu as l'habitude le mettre ainsi dans ton code ne t'embête pas. Tu te poseras la question lorsque tu constateras des lenteurs dans la réponse à cette requête ;)

                      • Partager sur Facebook
                      • Partager sur Twitter
                      Seul on va plus vite, ensemble on va plus loin ... A maîtriser : Conception BDD, MySQL, PHP/MySQL
                        23 novembre 2020 à 8:22:27

                        Encore une chose 

                        si on reprend cette image : 

                        Sur ma table cout j'ai une foreign key de id_element, id_secteur avec les tables Element et Secteur. 

                        Est ce qu'il ne serait pas mieux de mettre la foreign key avec la table Element_Secteur ?  

                        Edit : 

                        EDIT 2 : Il me faudrait combiner la liste de Date Evenement avec Cout, car le problème c'est qu'il me recopie la valeur précédente si il n'y a pas de date pour cout mais qu'il y en a une pour événement au lieux de mettre 0 et inversement ce ne me prend pas toutes les valeurs.

                        J'ai également un problème avec la deuxième sous-requête sur le graphique : 

                        -- Calcul du coût 2
                                        SELECT
                                            EV.date,
                                            SUM( E.cout * C.quantite ) AS cout2
                                        FROM
                                            evenement EV
                                                INNER JOIN Element_Secteur ES
                                                    ON EV.id_secteur = ES.id_secteur
                                                INNER JOIN Element E
                                                    ON ES.id_element = E.id_element
                                                INNER JOIN Cout C
                                                    ON ES.id_element = C.id_element
                                                    AND ES.id_secteur = C.id_secteur
                                        WHERE EV.id_secteur = '...'
                                        GROUP BY EV.date


                        J'obtient : 

                        Alors que j'aimerai obtenir ça : 

                        Ce que je change dans la sous-requete : 

                        -- Au lieu de EV.date
                        --JE FAIT
                        C.Date
                        
                        --ET dans le GROUP BY 
                        C.Date

                        le problème c'est quand j'essaye de réinjecter cela dans la requette ça ne fonctionne pas :( 

                        Je pense que c'est paracerque j'ai des date différente entre evenement et cout. 

                        De plus le cumul n'a pas l'air de prendre :( 

                        Je pense que je vais me rabattre vers le vb: 

                        Faire un

                        - i = count date : l'incrémenter

                        - cumulCout(i) += cout_tot

                        - DateCout(i) = date

                        Plot(date(i), cumulCout(i))  

                        Ca sera plus simple car j'ai déja passé pas mal de temps la dessus

                        EDIT : Peut être avec un UNION :?

                        SELECT
                            D.date,
                            SUM( C1.cout1 ) + SUM( C2.cout2 ) AS total,
                            @cumul := @cumul + SUM( C1.cout1 ) + SUM( C2.cout2 ) AS cumul
                        FROM
                            ( SELECT @cumul:=0 ) T,
                            (
                                -- Liste des dates possibles
                                SELECT DISTINCT date
                                FROM evenement
                            ) D
                                LEFT JOIN (
                                        -- Calcul du coût 1
                                        SELECT
                                            EV.date,
                                            SUM( EV.duree * 0.5 ) AS cout1
                                        FROM evenement EV
                                        WHERE EV.id_secteur = '...'
                                        GROUP BY EV.date
                                    ) C1
                                    ON D.date = C1.date
                                 
                        UNION ALL
                        
                        ( SELECT @cumul:=0 ) T2,
                            (
                                -- Liste des dates possibles
                                SELECT DISTINCT date
                                FROM element
                            ) E
                        
                                LEFT JOIN (
                                        -- Calcul du coût 2
                        ...

                        Je vais voir ce que ça donne de se côté... 

                        EDIT : 

                        APRES UNE LONGUE JOURNEE J'AI ENFIN REUSSI : 

                        Je suis passé par un UNION et un OVER ( PARTION BY ... ORDER BY...)

                        (Je ne sais pas pourquoi la variable ne s'incrémente plus quand il y a également une somme dans le SELECT ? ) 

                        L'entreprise est entrain de basculer sur la version 8.0 de MySQL 

                        Ca m'embête juste un peu car les tests sont encore réalisé sous une ancienne version :(

                        Après j'ai les date en Double c'est pas gênant dans le sens ou le control chart en VB me les fusionne automatiquement. (Distinct sur Date ne marche pas et je peux pas faire de GROUP BY avec OVER)

                         

                        EDIT : Je pense qu'il faut que je subdivise encore ne une sous requete qui me permet d'enlever OVER et de faire un GOUP BY

                        OK ça fonctionne :) 

                        -
                        Edité par DeveloSt 24 novembre 2020 à 9:32:29

                        • Partager sur Facebook
                        • Partager sur Twitter

                        Site Internet : https://devst.go.yj.fr

                        MySQL Somme Cumulée + Somme Cumulée + Group By

                        × 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