Partage
  • Partager sur Facebook
  • Partager sur Twitter

[MySQL-5.7] SQL et performances contre intuitive

    7 mai 2019 à 23:33:48

    Bonjour,

    Je travaille à la construction d'une matrice de formation d'agent générée en php dans laquelle ma requête est répétée autant de fois que j'ai d'item de formation (colonne).
    Nom : apercu.jpg Affichages : 16 Taille : 30,5 Ko
    Au delà de 7 items, la requête sql met plus 30 seconde à s’exécuter.
    Il faut évidemment creuser les performances de la requête et travailler les données pour améliorer.
    Seulement un point me bloque, si je demande la même requête sur l'ensemble des items, elle est alors très rapide sqlFull.zip.

    Pouvez vous m'orienter sur l'origine du pb ?
    Ci-dessous du code mis en forme avec en gras la séquence répétée n fois pour n items de formation (je génère dans le select une syntaxe HTML qui n'apparait pas ici d'où les "" à la place de <form>...</form> :

    select distinct concat( "
    ") as Qui 
    , if(cat32.STATUT is null," ", cat32.STATUT) as "" //séquence répétée n fois
    
    from 
    
        (SELECT distinct cybele_secteur_agent.CODE_AGENT, members.nom , members.prenom FROM cybele_secteur_agent 
        inner join members on members.id=cybele_secteur_agent.code_agent WHERE cybele_secteur_agent.CODE_SECTEUR and cybele_secteur_agent.CODE_AGENT in (0,138,139,150,151,154,115))
     as agent 
    
    //séquence ci dessous répétée n fois
    
    left join 
        (select cybele_hab_agent.CODE_AGENT, cybele_hab_agent.CODE_CAT_HAB, cybele_hab_agent.DATE_FORM, cybele_hab_agent.DATE_HAB, cybele_hab_agent.DATE_DESD_HAB_AGENT
    
        , if(cybele_hab_agent.DATE_DESD_HAB_AGENT is not null
        ,concat("+")
        , if( (susp.DATE_RETOUR_AGENT is null and datediff(now()    ,susp.mDATE_SUSP_AGENT) > cybele_cat_hab.DELAIS_REHAB) or (susp.DATE_RETOUR_AGENT is not null and datediff(susp.DATE_RETOUR_AGENT    ,susp.mDATE_SUSP_AGENT) > cybele_cat_hab.DELAIS_REHAB)    , if(maint.mDATE_MAINT is not null    , concat("a Rehabiliter")    , concat("Non Habilite"))    , if(maint.mDATE_MAINT is not null and datediff(now(),maint.mDATE_MAINT) < DELAIS-AJUSTEMENT    , if(maint.PARTIEL=1    , concat("Habilite Partiellement")    , concat("Habilite"))    , if(maint.mDATE_MAINT is not null and datediff(now()    ,maint.mDATE_MAINT) between DELAIS-AJUSTEMENT and DELAIS+AJUSTEMENT    , concat("a Maintenir")    , if(maint.mDATE_MAINT is not null and datediff(now()
        ,maint.mDATE_MAINT) > DELAIS+AJUSTEMENT    , concat("Depasse")    , if(maint.mDATE_MAINT is null and (cybele_hab_agent.DATE_FORM is not null or cybele_hab_agent.VAE=1)    , concat("Formation")    , concat("Non Habilite")))))) )    as STATUT 
    
        from cybele_hab_agent 
    
        inner join cybele_cat_hab on cybele_cat_hab.code_cat_hab=cybele_hab_agent.CODE_CAT_HAB 
    
    
    
        left JOIN
             (select cybele_agent_susp.CODE_MEMBERS, cybele_agent_susp.DATE_SUSP_AGENT as mDATE_SUSP_AGENT, cybele_agent_susp.DATE_RETOUR_AGENT 
            from cybele_agent_susp 
            inner join
                 (SELECT CODE_MEMBERS, max(DATE_SUSP_AGENT) as MaxD 
                FROM cybele_agent_susp 
                group by CODE_MEMBERS)
                    as MaxSusp on cybele_agent_susp.CODE_MEMBERS=MaxSusp.CODE_MEMBERS 
                            and cybele_agent_susp.DATE_SUSP_AGENT=MaxSusp.MaxD)
            as susp on cybele_hab_agent.CODE_AGENT=susp.CODE_MEMBERS 
            left JOIN
                (select cybele_maint_agent.CODE_AGENT
                , cybele_maint_agent.CODE_CAT_HAB
                , cybele_maint_agent.DATE_MAINT as mDATE_MAINT
                , cybele_maint_agent.COMMENTAIRE_MAINT
                , cybele_maint_agent.PARTIEL from cybele_maint_agent 
                inner join 
                    (SELECT CODE_AGENT, CODE_CAT_HAB, max(DATE_MAINT) as MaxD 
                    FROM cybele_maint_agent 
                    group by CODE_AGENT, CODE_CAT_HAB) 
                    as MaxMaint on cybele_maint_agent.CODE_AGENT=MaxMaint.CODE_AGENT 
                                and cybele_maint_agent.CODE_CAT_HAB=MaxMaint.CODE_CAT_HAB 
                                and cybele_maint_agent.DATE_MAINT=MaxMaint.MaxD) 
            as maint on cybele_hab_agent.CODE_AGENT=maint.CODE_AGENT 
                    and cybele_cat_hab.CODE_CAT_HAB=maint.CODE_CAT_HAB 
            where cybele_hab_agent.CODE_CAT_HAB=32) 
    as cat32 on agent.code_agent=cat32.code_agent 



    -
    Edité par guismo667 7 mai 2019 à 23:38:43

    • Partager sur Facebook
    • Partager sur Twitter
      8 mai 2019 à 14:50:40

      Bonjour,

      La requête me semble bien trop compliquée pour faire une simple matrice personne / formation ...

      Tant de sous-requêtes imbriquées qui plus est que tu répètes autant que besoin ...

      Peux-tu nous donner le modèle de données avec les 4 tables concernées, leurs relations, le fonctionnement de l'application (de quoi on parle), et le résultat attendu ?

      Selon moi il faut tout revoir ...

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

        Benzouye a écrit:

        Peux-tu nous donner le modèle de données avec les 4 tables concernées, leurs relations, le fonctionnement de l'application (de quoi on parle), et le résultat attendu ?

        • Partager sur Facebook
        • Partager sur Twitter
        Seul on va plus vite, ensemble on va plus loin ... A maîtriser : Conception BDD, MySQL, PHP/MySQL
          9 mai 2019 à 10:18:10

          Bonjour,

          Organisation:

          Un agent appartient à 1 ou + secteur
          Une habilitation appartient à 1 ou + secteur
          Un agent  peut avoir 1 ou + habilitation
          Un secteur a un cadre et ce cadre va quotidiennement consulter une matrice générale, état des lieux des échéances des habilitations.

          Cet affichage est le noyau de cet outil, il doit présenter en colonne les habilitations  exhaustives du secteur et en colonne la liste des agents actuellement dans ce secteur.

          ma requête consiste à extraire un statut pour chaque association  habilitation-Agent, ce statut dépend d'informations contenus dans différentes table puisque lié à l'agent (cybele_agent_susp) ou à l'habilitation (cybele_hab_agent) ou encore au maintient de cette habilitation dans le temps (cybele_maint_agent).

          je lance donc une requête qui calcul le statut de chaque agent pour une habilitation  comme ans l'exemple ci dessus avec

          as cat32 on agent.code_agent=cat32.code_agent


          pour l'habilitation 32.

          J'agrège en left join  chaque alias  (ex cat32) car tous les agents du secteur n'ont pas tous toutes les habilitations du secteur.

          Je suis très intéressé pas vos avis sur mon architecture !

          Mais à l'origine, je voulais surtout avoir des lumières d'experts sql sur la logique de recherche de mes latences.

          Comme expliqué ci-dessus, ma requête est identique quelque soit le nombre d'habilitation concernées, ce qui m'étonne, et ne m'inspire pas, c'est que les performances sont en courbes de gausse : au départ plus il y a d’habitation, plus les temps de requêtes sont longs, mais si je requête tous secteurs confondus, la requête est très rapide...

          merci d 'avance

          • Partager sur Facebook
          • Partager sur Twitter
            9 mai 2019 à 12:00:05

            guismo667 a écrit:

            je voulais surtout avoir des lumières d'experts sql sur la logique de recherche de mes latences.

            Ta sous-requête cat32 est déjà bien lourde, surtout si tu as beaucoup de données.

            En rajoutant une jointure externe (LEFT JOIN) tu augmentes encore le temps de traitement.

            En multipliant les sous-requêtes en jointure externe tu alourdis le traitement jusqu'à ce qu'il ne tienne plus en RAM ... et là c'est l'effondrement des performances ... qui semble arriver au 7ème critère ...

            guismo667 a écrit:

            Je suis très intéressé pas vos avis sur mon architecture

            Je ne remet pas en cause le modèle de données qui me paraît simple et efficace, mais seulement ta requête ... je trouve qu'il y a beaucoup de sous-requêtes imbriquées qui ne paraissent pas nécessaires au vu du besoin ...

            guismo667 a écrit:

            présenter en colonne les habilitations exhaustives du secteur et en colonne la liste des agents actuellement dans ce secteur

            Je partirai plus simplement d'un produit cartésien agent / habilitation, avec des sous-requêtes seulement pour déterminer le dernier maintien par agent/habilitation et les suspensions. La requête de base serait ainsi :

            SELECT
                SA.CODE_MEMBERS,
                H.CODE_CAT_HAB
                H.ACRONYME,
                IF( ASU.CODE_MEMBERS IS NULL, 0, 1 ) AS agent_suspendu,
                ...
            FROM
                cybele_secteur_agent SA
                    CROSS JOIN cybele_cat_hab H
                    LEFT JOIN (
                            -- Liste des agents suspendus
                            SELECT DISTINCT CODE_MEMBERS
                            FROM cybele_agent_susp
                            WHERE DATE_RETOUR_AGENT IS NULL
                        ) ASU
                        ON SA.CODE_MEMBERS = ASU.CODE_MEMBERS
                    LEFT JOIN cybele_hab_agent HA
                        ON SA.CODE_MEMBERS = HA.CODE_MEMBERS
                        AND H.CODE_CAT_HAB = HA.CODE_CAT_HAB
                    LEFT JOIN (
                            -- Dernier maintient par agent
                            SELECT CODE_MEMBERS, CODE_CAT_HAB, MAX( DATE_MAINT ) AS max_date
                            FROM cybele_maint_agent
                            GROUP BY CODE_MEMBERS, CODE_CAT_HAB
                        ) MMA
                        ON SA.CODE_MEMBERS = MMA.CODE_MEMBERS
                        AND H.CODE_CAT_HAB = MMA.CODE_CAT_HAB
                    LEFT JOIN cybele_maint_agent MA
                        ON MMA.CODE_MEMBERS = MA.CODE_MEMBERS
                        AND MMA.CODE_CAT_HAB = MA.CODE_CAT_HAB
                        AND MMA.max_date = MA.DATE_MAINT
            WHERE
                SA.CODE_SECTEUR = 'id secteur souhaité'
                AND H.CODE_SECTEUR = 'id secteur souhaité'

            Avec cela, dans ton SELECT tu peux faire tout tes tests pour afficher le statut voulu en fonction des informations retournées.

            Et une seule clause WHERE pour filtrer agents et habilitations en fonction du secteur.

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

              Benzouye a écrit:

              guismo667 a écrit:

              je voulais surtout avoir des lumières d'experts sql sur la logique de recherche de mes latences.

              Ta sous-requête cat32 est déjà bien lourde, surtout si tu as beaucoup de données.

              En rajoutant une jointure externe (LEFT JOIN) tu augmentes encore le temps de traitement.

              En multipliant les sous-requêtes en jointure externe tu alourdis le traitement jusqu'à ce qu'il ne tienne plus en RAM ... et là c'est l'effondrement des performances ... qui semble arriver au 7ème critère ...

              Et aurais tu une idée du pourquoi lorsque la requête est complete c'est à dire avec une 40 aine d'habilitation, la requete est instantanée ?

              C'est surtout cela qui m'étonne, des performance augmentant de façon linéaire, je peux comprendre mais là....

              guismo667 a écrit:

              Je suis très intéressé pas vos avis sur mon architecture

              Je ne remet pas en cause le modèle de données qui me paraît simple et efficace, mais seulement ta requête ... je trouve qu'il y a beaucoup de sous-requêtes imbriquées qui ne paraissent pas nécessaires au vu du besoin ...

              guismo667 a écrit:

              présenter en colonne les habilitations exhaustives du secteur et en colonne la liste des agents actuellement dans ce secteur

              Je partirai plus simplement d'un produit cartésien agent / habilitation, avec des sous-requêtes seulement pour déterminer le dernier maintien par agent/habilitation et les suspensions. La requête de base serait ainsi :

              SELECT
                  SA.CODE_MEMBERS,
                  H.CODE_CAT_HAB
                  H.ACRONYME,
                  IF( ASU.CODE_MEMBERS IS NULL, 0, 1 ) AS agent_suspendu,
                  ...
              FROM
                  cybele_secteur_agent SA
                      CROSS JOIN cybele_cat_hab H
                      LEFT JOIN (
                              -- Liste des agents suspendus
                              SELECT DISTINCT CODE_MEMBERS
                              FROM cybele_agent_susp
                              WHERE DATE_RETOUR_AGENT IS NULL
                          ) ASU
                          ON SA.CODE_MEMBERS = ASU.CODE_MEMBERS
                      LEFT JOIN cybele_hab_agent HA
                          ON SA.CODE_MEMBERS = HA.CODE_MEMBERS
                          AND H.CODE_CAT_HAB = HA.CODE_CAT_HAB
                      LEFT JOIN (
                              -- Dernier maintient par agent
                              SELECT CODE_MEMBERS, CODE_CAT_HAB, MAX( DATE_MAINT ) AS max_date
                              FROM cybele_maint_agent
                              GROUP BY CODE_MEMBERS, CODE_CAT_HAB
                          ) MMA
                          ON SA.CODE_MEMBERS = MMA.CODE_MEMBERS
                          AND H.CODE_CAT_HAB = MMA.CODE_CAT_HAB
                      LEFT JOIN cybele_maint_agent MA
                          ON MMA.CODE_MEMBERS = MA.CODE_MEMBERS
                          AND MMA.CODE_CAT_HAB = MA.CODE_CAT_HAB
                          AND MMA.max_date = MA.DATE_MAINT
              WHERE
                  SA.CODE_SECTEUR = 'id secteur souhaité'
                  AND H.CODE_SECTEUR = 'id secteur souhaité'

              Avec cela, dans ton SELECT tu peux faire tout tes tests pour afficher le statut voulu en fonction des informations retournées.

              Et une seule clause WHERE pour filtrer agents et habilitations en fonction du secteur.

              Super, et bravo, pas facile de rentrer dans un code inconnu, je teste cela au plus vite et te redis car  je ne te l'ai pas dis, nous sommes en phase projet, donc on vient de tout vider et remplir la bdd.

              Merci pour ton aide



              • Partager sur Facebook
              • Partager sur Twitter
                9 mai 2019 à 15:13:59

                guismo667 a écrit:

                Aurais tu une idée du pourquoi lorsque la requête est complete c'est à dire avec une 40 aine d'habilitation, la requete est instantanée ?

                Car il n'y a pas de sous-requête en jointure externe non ? Peux-tu poster les requêtes complètes ? Celle qui rame et celle qui est instantanée ?

                -
                Edité par Benzouye 9 mai 2019 à 15:14:12

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

                  Le sqlfull.zip de ma première demande est très rapide (3 secondes pour 42 alias ou 42 habilitations)  et correspond à la matrice complète mais je ne l'ai ps indenté comme la requête  insérée dans le post.

                  celle donnée dans le post correspond à un secteur à 1 catégorie donc assez rapide (0.1 seconde).

                  et ci dessous celle très lente (60 secondes pour 7 habilitations).

                  ______________

                  Up de 16:44 :

                  Une indication peut-être, mon collègue fait crée les habilitations et les agents mais ne remplis pas les dates.

                  Les performances sont mauvaises si le nombre d'habilitations et >7 et interminable pour la matrice complète, on dirait bien que la requête supporte mal le manque de remplissage de certaines données.... une histoire d'index peut-être ?

                  (je travaille à tester ta requête...)

                  ____________

                  Up 16:51

                  JE viens de découvrir quelque chose :

                  si plus j'ajoute de critère pour réduire le nombre d’enregistrement de la sous requête :

                  LEFT JOIN  (select  cybele_maint_agent.CODE_AGENT, cybele_maint_agent.CODE_CAT_HAB, cybele_maint_agent.DATE_MAINT as mDATE_MAINT, cybele_maint_agent.COMMENTAIRE_MAINT,  cybele_maint_agent.PARTIEL 
                          from cybele_maint_agent 
                              INNER join 
                                  (SELECT  CODE_AGENT, CODE_CAT_HAB, max(DATE_MAINT) as MaxD
                                  FROM cybele_maint_agent
                                  Where cybele_maint_agent.CODE_AGENT in ('.$sqlAgent.')
                                  and cybele_maint_agent.CODE_CAT_HAB='.$resreqHab['CODE_CAT_HAB'].'
                                  group by CODE_AGENT, CODE_CAT_HAB) as MaxMaint 
                              on cybele_maint_agent.CODE_AGENT=MaxMaint.CODE_AGENT
                              and cybele_maint_agent.CODE_CAT_HAB=MaxMaint.CODE_CAT_HAB
                              and cybele_maint_agent.DATE_MAINT=MaxMaint.MaxD) as  maint

                  Plus la requête est longue... je me disais qu'être plus selectif dans chaque sous requête diminuerai le temps de traitement mais j'observe nettement le contraire :

                  sans le inner join : 5 secondes pour la matrice complète

                  avec le inner join  mais sans les clauses Where de MaxMaint : 30 secondes

                  avec  les clauses Where 120 secondes de MaxMaint....

                  En espérant que ces indications puissent être utilses

                  ___________

                  select distinct concat( "
                  ") as Qui 
                  , if(cat32.STATUT is null," ", cat32.STATUT) as "
                  "
                  , if(cat25.STATUT is null," ", cat25.STATUT) as "
                  "
                  , if(cat33.STATUT is null," ", cat33.STATUT) as "
                  "
                  , if(cat29.STATUT is null," ", cat29.STATUT) as "
                  "
                  , if(cat30.STATUT is null," ", cat30.STATUT) as "
                  "
                  , if(cat34.STATUT is null," ", cat34.STATUT) as "
                  "
                  , if(cat31.STATUT is null," ", cat31.STATUT) as "
                  " from 
                  
                      (SELECT distinct cybele_secteur_agent.CODE_AGENT, members.nom , members.prenom FROM cybele_secteur_agent 
                      inner join members on members.id=cybele_secteur_agent.code_agent WHERE cybele_secteur_agent.CODE_SECTEUR and cybele_secteur_agent.CODE_AGENT in (0,138,139,150,151,154,115))
                   as agent 
                  
                  left join 
                      (select cybele_hab_agent.CODE_AGENT, cybele_hab_agent.CODE_CAT_HAB, cybele_hab_agent.DATE_FORM, cybele_hab_agent.DATE_HAB, cybele_hab_agent.DATE_DESD_HAB_AGENT
                  
                      , if(cybele_hab_agent.DATE_DESD_HAB_AGENT is not null
                      ,concat("+")
                      , if( (susp.DATE_RETOUR_AGENT is null and datediff(now()
                      ,susp.mDATE_SUSP_AGENT) > cybele_cat_hab.DELAIS_REHAB) or (susp.DATE_RETOUR_AGENT is not null and datediff(susp.DATE_RETOUR_AGENT
                      ,susp.mDATE_SUSP_AGENT) > cybele_cat_hab.DELAIS_REHAB)
                      , if(maint.mDATE_MAINT is not null
                      , concat("a Rehabiliter")
                      , concat("Non Habilite"))
                      , if(maint.mDATE_MAINT is not null and datediff(now()
                      ,maint.mDATE_MAINT) < DELAIS-AJUSTEMENT
                      , if(maint.PARTIEL=1
                      , concat("Habilite Partiellement")
                      , concat("Habilite"))
                      , if(maint.mDATE_MAINT is not null and datediff(now()
                      ,maint.mDATE_MAINT) between DELAIS-AJUSTEMENT and DELAIS+AJUSTEMENT
                      , concat("a Maintenir")
                      , if(maint.mDATE_MAINT is not null and datediff(now()
                      ,maint.mDATE_MAINT) > DELAIS+AJUSTEMENT
                      , concat("Depasse")
                      , if(maint.mDATE_MAINT is null and (cybele_hab_agent.DATE_FORM is not null or cybele_hab_agent.VAE=1)
                      , concat("Formation")
                      , concat("Non Habilite")))))) )
                  as STATUT 
                  
                  from cybele_hab_agent 
                  
                  inner join cybele_cat_hab on cybele_cat_hab.code_cat_hab=cybele_hab_agent.CODE_CAT_HAB 
                  
                  left JOIN
                       (select cybele_agent_susp.CODE_MEMBERS, cybele_agent_susp.DATE_SUSP_AGENT as mDATE_SUSP_AGENT, cybele_agent_susp.DATE_RETOUR_AGENT 
                      from cybele_agent_susp 
                      inner join
                           (SELECT CODE_MEMBERS, max(DATE_SUSP_AGENT) as MaxD 
                          FROM cybele_agent_susp 
                          group by CODE_MEMBERS)
                              as MaxSusp on cybele_agent_susp.CODE_MEMBERS=MaxSusp.CODE_MEMBERS 
                                      and cybele_agent_susp.DATE_SUSP_AGENT=MaxSusp.MaxD)
                      as susp on cybele_hab_agent.CODE_AGENT=susp.CODE_MEMBERS 
                      left JOIN
                          (select cybele_maint_agent.CODE_AGENT
                          , cybele_maint_agent.CODE_CAT_HAB
                          , cybele_maint_agent.DATE_MAINT as mDATE_MAINT
                          , cybele_maint_agent.COMMENTAIRE_MAINT
                          , cybele_maint_agent.PARTIEL from cybele_maint_agent 
                          inner join 
                              (SELECT CODE_AGENT, CODE_CAT_HAB, max(DATE_MAINT) as MaxD 
                              FROM cybele_maint_agent 
                              group by CODE_AGENT, CODE_CAT_HAB) 
                              as MaxMaint on cybele_maint_agent.CODE_AGENT=MaxMaint.CODE_AGENT 
                                          and cybele_maint_agent.CODE_CAT_HAB=MaxMaint.CODE_CAT_HAB 
                                          and cybele_maint_agent.DATE_MAINT=MaxMaint.MaxD) 
                      as maint on cybele_hab_agent.CODE_AGENT=maint.CODE_AGENT 
                              and cybele_cat_hab.CODE_CAT_HAB=maint.CODE_CAT_HAB 
                      where cybele_hab_agent.CODE_CAT_HAB=32) 
                  as cat32 on agent.code_agent=cat32.code_agent 
                  
                  left join (select cybele_hab_agent.CODE_AGENT, cybele_hab_agent.CODE_CAT_HAB, cybele_hab_agent.DATE_FORM, cybele_hab_agent.DATE_HAB, cybele_hab_agent.DATE_DESD_HAB_AGENT
                  , if(cybele_hab_agent.DATE_DESD_HAB_AGENT is not null
                  ,concat("+")
                  , if( (susp.DATE_RETOUR_AGENT is null and datediff(now()
                  ,susp.mDATE_SUSP_AGENT) > cybele_cat_hab.DELAIS_REHAB) or (susp.DATE_RETOUR_AGENT is not null and datediff(susp.DATE_RETOUR_AGENT
                  ,susp.mDATE_SUSP_AGENT) > cybele_cat_hab.DELAIS_REHAB)
                  , if(maint.mDATE_MAINT is not null
                  , concat("a Rehabiliter")
                  , concat("Non Habilite"))
                  , if(maint.mDATE_MAINT is not null and datediff(now()
                  ,maint.mDATE_MAINT) < DELAIS-AJUSTEMENT
                  , if(maint.PARTIEL=1
                  , concat("Habilite Partiellement")
                  , concat("Habilite"))
                  , if(maint.mDATE_MAINT is not null and datediff(now()
                  ,maint.mDATE_MAINT) between DELAIS-AJUSTEMENT and DELAIS+AJUSTEMENT
                  , concat("a Maintenir")
                  , if(maint.mDATE_MAINT is not null and datediff(now()
                  ,maint.mDATE_MAINT) > DELAIS+AJUSTEMENT
                  , concat("Depasse")
                  , if(maint.mDATE_MAINT is null and (cybele_hab_agent.DATE_FORM is not null or cybele_hab_agent.VAE=1)
                  , concat("Formation")
                  , concat("Non Habilite")))))) ) as STATUT from cybele_hab_agent 
                  inner join cybele_cat_hab on cybele_cat_hab.code_cat_hab=cybele_hab_agent.CODE_CAT_HAB 
                  left JOIN (select cybele_agent_susp.CODE_MEMBERS
                  , cybele_agent_susp.DATE_SUSP_AGENT as mDATE_SUSP_AGENT
                  , cybele_agent_susp.DATE_RETOUR_AGENT from cybele_agent_susp 
                  inner join (SELECT CODE_MEMBERS
                  , max(DATE_SUSP_AGENT) as MaxD FROM cybele_agent_susp group by CODE_MEMBERS) as MaxSusp on cybele_agent_susp.CODE_MEMBERS=MaxSusp.CODE_MEMBERS and cybele_agent_susp.DATE_SUSP_AGENT=MaxSusp.MaxD) as susp on cybele_hab_agent.CODE_AGENT=susp.CODE_MEMBERS 
                  left JOIN (select cybele_maint_agent.CODE_AGENT
                  , cybele_maint_agent.CODE_CAT_HAB
                  , cybele_maint_agent.DATE_MAINT as mDATE_MAINT
                  , cybele_maint_agent.COMMENTAIRE_MAINT
                  , cybele_maint_agent.PARTIEL from cybele_maint_agent 
                  inner join (SELECT CODE_AGENT
                  , CODE_CAT_HAB
                  , max(DATE_MAINT) as MaxD FROM cybele_maint_agent group by CODE_AGENT
                  , CODE_CAT_HAB) as MaxMaint on cybele_maint_agent.CODE_AGENT=MaxMaint.CODE_AGENT and cybele_maint_agent.CODE_CAT_HAB=MaxMaint.CODE_CAT_HAB and cybele_maint_agent.DATE_MAINT=MaxMaint.MaxD) as maint on cybele_hab_agent.CODE_AGENT=maint.CODE_AGENT and cybele_cat_hab.CODE_CAT_HAB=maint.CODE_CAT_HAB where cybele_hab_agent.CODE_CAT_HAB=25) as cat25 
                  
                  on agent.code_agent=cat25.code_agent 
                  left join (select cybele_hab_agent.CODE_AGENT
                  , cybele_hab_agent.CODE_CAT_HAB
                  , cybele_hab_agent.DATE_FORM
                  , cybele_hab_agent.DATE_HAB
                  , cybele_hab_agent.DATE_DESD_HAB_AGENT
                  , if(cybele_hab_agent.DATE_DESD_HAB_AGENT is not null
                  ,concat("+")
                  , if( (susp.DATE_RETOUR_AGENT is null and datediff(now()
                  ,susp.mDATE_SUSP_AGENT) > cybele_cat_hab.DELAIS_REHAB) or (susp.DATE_RETOUR_AGENT is not null and datediff(susp.DATE_RETOUR_AGENT
                  ,susp.mDATE_SUSP_AGENT) > cybele_cat_hab.DELAIS_REHAB)
                  , if(maint.mDATE_MAINT is not null
                  , concat("a Rehabiliter")
                  , concat("Non Habilite"))
                  , if(maint.mDATE_MAINT is not null and datediff(now()
                  ,maint.mDATE_MAINT) < DELAIS-AJUSTEMENT
                  , if(maint.PARTIEL=1
                  , concat("Habilite Partiellement")
                  , concat("Habilite"))
                  , if(maint.mDATE_MAINT is not null and datediff(now()
                  ,maint.mDATE_MAINT) between DELAIS-AJUSTEMENT and DELAIS+AJUSTEMENT
                  , concat("a Maintenir")
                  , if(maint.mDATE_MAINT is not null and datediff(now()
                  ,maint.mDATE_MAINT) > DELAIS+AJUSTEMENT
                  , concat("Depasse")
                  , if(maint.mDATE_MAINT is null and (cybele_hab_agent.DATE_FORM is not null or cybele_hab_agent.VAE=1)
                  , concat("Formation")
                  , concat("Non Habilite")))))) ) as STATUT from cybele_hab_agent 
                  inner join cybele_cat_hab on cybele_cat_hab.code_cat_hab=cybele_hab_agent.CODE_CAT_HAB 
                  left JOIN (select cybele_agent_susp.CODE_MEMBERS
                  , cybele_agent_susp.DATE_SUSP_AGENT as mDATE_SUSP_AGENT
                  , cybele_agent_susp.DATE_RETOUR_AGENT from cybele_agent_susp 
                  inner join (SELECT CODE_MEMBERS
                  , max(DATE_SUSP_AGENT) as MaxD FROM cybele_agent_susp group by CODE_MEMBERS) as MaxSusp on cybele_agent_susp.CODE_MEMBERS=MaxSusp.CODE_MEMBERS and cybele_agent_susp.DATE_SUSP_AGENT=MaxSusp.MaxD) as susp on cybele_hab_agent.CODE_AGENT=susp.CODE_MEMBERS 
                  left JOIN (select cybele_maint_agent.CODE_AGENT
                  , cybele_maint_agent.CODE_CAT_HAB
                  , cybele_maint_agent.DATE_MAINT as mDATE_MAINT
                  , cybele_maint_agent.COMMENTAIRE_MAINT
                  , cybele_maint_agent.PARTIEL from cybele_maint_agent 
                  inner join (SELECT CODE_AGENT
                  , CODE_CAT_HAB
                  , max(DATE_MAINT) as MaxD FROM cybele_maint_agent group by CODE_AGENT
                  , CODE_CAT_HAB) as MaxMaint on cybele_maint_agent.CODE_AGENT=MaxMaint.CODE_AGENT and cybele_maint_agent.CODE_CAT_HAB=MaxMaint.CODE_CAT_HAB and cybele_maint_agent.DATE_MAINT=MaxMaint.MaxD) as maint on cybele_hab_agent.CODE_AGENT=maint.CODE_AGENT and cybele_cat_hab.CODE_CAT_HAB=maint.CODE_CAT_HAB where cybele_hab_agent.CODE_CAT_HAB=33) as cat33 
                  
                  on agent.code_agent=cat33.code_agent 
                  left join (select cybele_hab_agent.CODE_AGENT
                  , cybele_hab_agent.CODE_CAT_HAB
                  , cybele_hab_agent.DATE_FORM
                  , cybele_hab_agent.DATE_HAB
                  , cybele_hab_agent.DATE_DESD_HAB_AGENT
                  , if(cybele_hab_agent.DATE_DESD_HAB_AGENT is not null
                  ,concat("+")
                  , if( (susp.DATE_RETOUR_AGENT is null and datediff(now()
                  ,susp.mDATE_SUSP_AGENT) > cybele_cat_hab.DELAIS_REHAB) or (susp.DATE_RETOUR_AGENT is not null and datediff(susp.DATE_RETOUR_AGENT
                  ,susp.mDATE_SUSP_AGENT) > cybele_cat_hab.DELAIS_REHAB)
                  , if(maint.mDATE_MAINT is not null
                  , concat("a Rehabiliter")
                  , concat("Non Habilite"))
                  , if(maint.mDATE_MAINT is not null and datediff(now()
                  ,maint.mDATE_MAINT) < DELAIS-AJUSTEMENT
                  , if(maint.PARTIEL=1
                  , concat("Habilite Partiellement")
                  , concat("Habilite"))
                  , if(maint.mDATE_MAINT is not null and datediff(now()
                  ,maint.mDATE_MAINT) between DELAIS-AJUSTEMENT and DELAIS+AJUSTEMENT
                  , concat("a Maintenir")
                  , if(maint.mDATE_MAINT is not null and datediff(now()
                  ,maint.mDATE_MAINT) > DELAIS+AJUSTEMENT
                  , concat("Depasse")
                  , if(maint.mDATE_MAINT is null and (cybele_hab_agent.DATE_FORM is not null or cybele_hab_agent.VAE=1)
                  , concat("Formation")
                  , concat("Non Habilite")))))) ) as STATUT from cybele_hab_agent 
                  inner join cybele_cat_hab on cybele_cat_hab.code_cat_hab=cybele_hab_agent.CODE_CAT_HAB 
                  left JOIN (select cybele_agent_susp.CODE_MEMBERS
                  , cybele_agent_susp.DATE_SUSP_AGENT as mDATE_SUSP_AGENT
                  , cybele_agent_susp.DATE_RETOUR_AGENT from cybele_agent_susp 
                  inner join (SELECT CODE_MEMBERS
                  , max(DATE_SUSP_AGENT) as MaxD FROM cybele_agent_susp group by CODE_MEMBERS) as MaxSusp on cybele_agent_susp.CODE_MEMBERS=MaxSusp.CODE_MEMBERS and cybele_agent_susp.DATE_SUSP_AGENT=MaxSusp.MaxD) as susp on cybele_hab_agent.CODE_AGENT=susp.CODE_MEMBERS 
                  left JOIN (select cybele_maint_agent.CODE_AGENT
                  , cybele_maint_agent.CODE_CAT_HAB
                  , cybele_maint_agent.DATE_MAINT as mDATE_MAINT
                  , cybele_maint_agent.COMMENTAIRE_MAINT
                  , cybele_maint_agent.PARTIEL from cybele_maint_agent 
                  inner join (SELECT CODE_AGENT
                  , CODE_CAT_HAB
                  , max(DATE_MAINT) as MaxD FROM cybele_maint_agent group by CODE_AGENT
                  , CODE_CAT_HAB) as MaxMaint on cybele_maint_agent.CODE_AGENT=MaxMaint.CODE_AGENT and cybele_maint_agent.CODE_CAT_HAB=MaxMaint.CODE_CAT_HAB and cybele_maint_agent.DATE_MAINT=MaxMaint.MaxD) as maint on cybele_hab_agent.CODE_AGENT=maint.CODE_AGENT and cybele_cat_hab.CODE_CAT_HAB=maint.CODE_CAT_HAB where cybele_hab_agent.CODE_CAT_HAB=29) as cat29 
                  
                  on agent.code_agent=cat29.code_agent 
                  left join (select cybele_hab_agent.CODE_AGENT
                  , cybele_hab_agent.CODE_CAT_HAB
                  , cybele_hab_agent.DATE_FORM
                  , cybele_hab_agent.DATE_HAB
                  , cybele_hab_agent.DATE_DESD_HAB_AGENT
                  , if(cybele_hab_agent.DATE_DESD_HAB_AGENT is not null
                  ,concat("+")
                  , if( (susp.DATE_RETOUR_AGENT is null and datediff(now()
                  ,susp.mDATE_SUSP_AGENT) > cybele_cat_hab.DELAIS_REHAB) or (susp.DATE_RETOUR_AGENT is not null and datediff(susp.DATE_RETOUR_AGENT
                  ,susp.mDATE_SUSP_AGENT) > cybele_cat_hab.DELAIS_REHAB)
                  , if(maint.mDATE_MAINT is not null
                  , concat("a Rehabiliter")
                  , concat("Non Habilite"))
                  , if(maint.mDATE_MAINT is not null and datediff(now()
                  ,maint.mDATE_MAINT) < DELAIS-AJUSTEMENT
                  , if(maint.PARTIEL=1
                  , concat("Habilite Partiellement")
                  , concat("Habilite"))
                  , if(maint.mDATE_MAINT is not null and datediff(now()
                  ,maint.mDATE_MAINT) between DELAIS-AJUSTEMENT and DELAIS+AJUSTEMENT
                  , concat("a Maintenir")
                  , if(maint.mDATE_MAINT is not null and datediff(now()
                  ,maint.mDATE_MAINT) > DELAIS+AJUSTEMENT
                  , concat("Depasse")
                  , if(maint.mDATE_MAINT is null and (cybele_hab_agent.DATE_FORM is not null or cybele_hab_agent.VAE=1)
                  , concat("Formation")
                  , concat("Non Habilite")))))) ) as STATUT from cybele_hab_agent 
                  inner join cybele_cat_hab on cybele_cat_hab.code_cat_hab=cybele_hab_agent.CODE_CAT_HAB 
                  left JOIN (select cybele_agent_susp.CODE_MEMBERS
                  , cybele_agent_susp.DATE_SUSP_AGENT as mDATE_SUSP_AGENT
                  , cybele_agent_susp.DATE_RETOUR_AGENT from cybele_agent_susp 
                  inner join (SELECT CODE_MEMBERS
                  , max(DATE_SUSP_AGENT) as MaxD FROM cybele_agent_susp group by CODE_MEMBERS) as MaxSusp on cybele_agent_susp.CODE_MEMBERS=MaxSusp.CODE_MEMBERS and cybele_agent_susp.DATE_SUSP_AGENT=MaxSusp.MaxD) as susp on cybele_hab_agent.CODE_AGENT=susp.CODE_MEMBERS 
                  left JOIN (select cybele_maint_agent.CODE_AGENT
                  , cybele_maint_agent.CODE_CAT_HAB
                  , cybele_maint_agent.DATE_MAINT as mDATE_MAINT
                  , cybele_maint_agent.COMMENTAIRE_MAINT
                  , cybele_maint_agent.PARTIEL from cybele_maint_agent 
                  inner join (SELECT CODE_AGENT
                  , CODE_CAT_HAB
                  , max(DATE_MAINT) as MaxD FROM cybele_maint_agent group by CODE_AGENT
                  , CODE_CAT_HAB) as MaxMaint on cybele_maint_agent.CODE_AGENT=MaxMaint.CODE_AGENT and cybele_maint_agent.CODE_CAT_HAB=MaxMaint.CODE_CAT_HAB and cybele_maint_agent.DATE_MAINT=MaxMaint.MaxD) as maint on cybele_hab_agent.CODE_AGENT=maint.CODE_AGENT and cybele_cat_hab.CODE_CAT_HAB=maint.CODE_CAT_HAB where cybele_hab_agent.CODE_CAT_HAB=30) as cat30 
                  
                  on agent.code_agent=cat30.code_agent 
                  left join (select cybele_hab_agent.CODE_AGENT
                  , cybele_hab_agent.CODE_CAT_HAB
                  , cybele_hab_agent.DATE_FORM
                  , cybele_hab_agent.DATE_HAB
                  , cybele_hab_agent.DATE_DESD_HAB_AGENT
                  , if(cybele_hab_agent.DATE_DESD_HAB_AGENT is not null
                  ,concat("+")
                  , if( (susp.DATE_RETOUR_AGENT is null and datediff(now()
                  ,susp.mDATE_SUSP_AGENT) > cybele_cat_hab.DELAIS_REHAB) or (susp.DATE_RETOUR_AGENT is not null and datediff(susp.DATE_RETOUR_AGENT
                  ,susp.mDATE_SUSP_AGENT) > cybele_cat_hab.DELAIS_REHAB)
                  , if(maint.mDATE_MAINT is not null
                  , concat("a Rehabiliter")
                  , concat("Non Habilite"))
                  , if(maint.mDATE_MAINT is not null and datediff(now()
                  ,maint.mDATE_MAINT) < DELAIS-AJUSTEMENT
                  , if(maint.PARTIEL=1
                  , concat("Habilite Partiellement")
                  , concat("Habilite"))
                  , if(maint.mDATE_MAINT is not null and datediff(now()
                  ,maint.mDATE_MAINT) between DELAIS-AJUSTEMENT and DELAIS+AJUSTEMENT
                  , concat("a Maintenir")
                  , if(maint.mDATE_MAINT is not null and datediff(now()
                  ,maint.mDATE_MAINT) > DELAIS+AJUSTEMENT
                  , concat("Depasse")
                  , if(maint.mDATE_MAINT is null and (cybele_hab_agent.DATE_FORM is not null or cybele_hab_agent.VAE=1)
                  , concat("Formation")
                  , concat("Non Habilite")))))) ) as STATUT from cybele_hab_agent 
                  inner join cybele_cat_hab on cybele_cat_hab.code_cat_hab=cybele_hab_agent.CODE_CAT_HAB 
                  left JOIN (select cybele_agent_susp.CODE_MEMBERS
                  , cybele_agent_susp.DATE_SUSP_AGENT as mDATE_SUSP_AGENT
                  , cybele_agent_susp.DATE_RETOUR_AGENT from cybele_agent_susp 
                  inner join (SELECT CODE_MEMBERS
                  , max(DATE_SUSP_AGENT) as MaxD FROM cybele_agent_susp group by CODE_MEMBERS) as MaxSusp on cybele_agent_susp.CODE_MEMBERS=MaxSusp.CODE_MEMBERS and cybele_agent_susp.DATE_SUSP_AGENT=MaxSusp.MaxD) as susp on cybele_hab_agent.CODE_AGENT=susp.CODE_MEMBERS 
                  left JOIN (select cybele_maint_agent.CODE_AGENT
                  , cybele_maint_agent.CODE_CAT_HAB
                  , cybele_maint_agent.DATE_MAINT as mDATE_MAINT
                  , cybele_maint_agent.COMMENTAIRE_MAINT
                  , cybele_maint_agent.PARTIEL from cybele_maint_agent 
                  inner join (SELECT CODE_AGENT
                  , CODE_CAT_HAB
                  , max(DATE_MAINT) as MaxD FROM cybele_maint_agent group by CODE_AGENT
                  , CODE_CAT_HAB) as MaxMaint on cybele_maint_agent.CODE_AGENT=MaxMaint.CODE_AGENT and cybele_maint_agent.CODE_CAT_HAB=MaxMaint.CODE_CAT_HAB and cybele_maint_agent.DATE_MAINT=MaxMaint.MaxD) as maint on cybele_hab_agent.CODE_AGENT=maint.CODE_AGENT and cybele_cat_hab.CODE_CAT_HAB=maint.CODE_CAT_HAB where cybele_hab_agent.CODE_CAT_HAB=34) as cat34 
                  
                  on agent.code_agent=cat34.code_agent 
                  left join (select cybele_hab_agent.CODE_AGENT
                  , cybele_hab_agent.CODE_CAT_HAB
                  , cybele_hab_agent.DATE_FORM
                  , cybele_hab_agent.DATE_HAB
                  , cybele_hab_agent.DATE_DESD_HAB_AGENT
                  , if(cybele_hab_agent.DATE_DESD_HAB_AGENT is not null
                  ,concat("+")
                  , if( (susp.DATE_RETOUR_AGENT is null and datediff(now()
                  ,susp.mDATE_SUSP_AGENT) > cybele_cat_hab.DELAIS_REHAB) or (susp.DATE_RETOUR_AGENT is not null and datediff(susp.DATE_RETOUR_AGENT
                  ,susp.mDATE_SUSP_AGENT) > cybele_cat_hab.DELAIS_REHAB)
                  , if(maint.mDATE_MAINT is not null
                  , concat("a Rehabiliter")
                  , concat("Non Habilite"))
                  , if(maint.mDATE_MAINT is not null and datediff(now()
                  ,maint.mDATE_MAINT) < DELAIS-AJUSTEMENT
                  , if(maint.PARTIEL=1
                  , concat("Habilite Partiellement")
                  , concat("Habilite"))
                  , if(maint.mDATE_MAINT is not null and datediff(now()
                  ,maint.mDATE_MAINT) between DELAIS-AJUSTEMENT and DELAIS+AJUSTEMENT
                  , concat("a Maintenir")
                  , if(maint.mDATE_MAINT is not null and datediff(now()
                  ,maint.mDATE_MAINT) > DELAIS+AJUSTEMENT
                  , concat("Depasse")
                  , if(maint.mDATE_MAINT is null and (cybele_hab_agent.DATE_FORM is not null or cybele_hab_agent.VAE=1)
                  , concat("Formation")
                  , concat("Non Habilite")))))) ) as STATUT from cybele_hab_agent 
                  inner join cybele_cat_hab on cybele_cat_hab.code_cat_hab=cybele_hab_agent.CODE_CAT_HAB 
                  left JOIN (select cybele_agent_susp.CODE_MEMBERS
                  , cybele_agent_susp.DATE_SUSP_AGENT as mDATE_SUSP_AGENT
                  , cybele_agent_susp.DATE_RETOUR_AGENT from cybele_agent_susp 
                  inner join (SELECT CODE_MEMBERS
                  , max(DATE_SUSP_AGENT) as MaxD FROM cybele_agent_susp group by CODE_MEMBERS) as MaxSusp on cybele_agent_susp.CODE_MEMBERS=MaxSusp.CODE_MEMBERS and cybele_agent_susp.DATE_SUSP_AGENT=MaxSusp.MaxD) as susp on cybele_hab_agent.CODE_AGENT=susp.CODE_MEMBERS 
                  left JOIN (select cybele_maint_agent.CODE_AGENT
                  , cybele_maint_agent.CODE_CAT_HAB
                  , cybele_maint_agent.DATE_MAINT as mDATE_MAINT
                  , cybele_maint_agent.COMMENTAIRE_MAINT
                  , cybele_maint_agent.PARTIEL from cybele_maint_agent 
                  inner join (SELECT CODE_AGENT
                  , CODE_CAT_HAB
                  , max(DATE_MAINT) as MaxD FROM cybele_maint_agent group by CODE_AGENT
                  , CODE_CAT_HAB) as MaxMaint on cybele_maint_agent.CODE_AGENT=MaxMaint.CODE_AGENT and cybele_maint_agent.CODE_CAT_HAB=MaxMaint.CODE_CAT_HAB and cybele_maint_agent.DATE_MAINT=MaxMaint.MaxD) as maint on cybele_hab_agent.CODE_AGENT=maint.CODE_AGENT and cybele_cat_hab.CODE_CAT_HAB=maint.CODE_CAT_HAB where cybele_hab_agent.CODE_CAT_HAB=31) as cat31 on agent.code_agent=cat31.code_agent order by agent.nom
                  , agent.prenom 



                  -
                  Edité par guismo667 9 mai 2019 à 16:55:15

                  • Partager sur Facebook
                  • Partager sur Twitter
                    9 mai 2019 à 17:31:58

                    Je n'avais pas vu le .ZIP :p

                    Globalement la requête n'est pas optimisée.

                    Tu répètes X fois la même sous requête en changeant simplement le code secteur ... cela ne t'as pas mis la puce à l'oreille que tu faisais un truc TROP laborieux ?

                    Ensuite, tu cherches à faire un tableau croisé dynamique (pivot table en anglais). MySQL avant sa version 8 n'intègre pas de gestion des PIVOT, et même si tu étais en version 8 je te ferais le même conseil : c'est du rôle de l'application que de mettre en forme tes données sous-forme de tableau croisé, pas à SQL ...

                    Je pense qu'il est beaucoup plus pertinent de faire une requête en tableau droit (comme SQL sait très bien faire naturellement) et de "croiser" les données dans ton code applicatif (PHP ?).

                    L'idée c'est donc de partir sur la base de la requête donnée plus tôt, et d'y ajouter le code secteur comme discriminant :

                    SELECT
                        SA.CODE_SECTEUR,
                        SA.CODE_MEMBERS,
                        H.CODE_CAT_HAB,
                        H.ACRONYME,
                        IF(
                            HA.DATE_DESD_HAB_AGENT IS NOT NULL,
                            "+",
                            IF(
                                (
                                    ASU.CODE_MEMBERS IS NOT NULL
                                    AND ASU.DATE_RETOUR_AGENT IS NULL
                                    AND DATEDIFF( NOW(), ASU.DATE_SUSP_AGENT ) > H.DELAIS_REHAB
                                ) OR (
                                    ASU.DATE_RETOUR_AGENT IS NOT NULL
                                    AND DATEDIFF( ASU.DATE_RETOUR_AGENT, ASU.DATE_SUSP_AGENT ) > H.DELAIS_REHAB
                                ),
                                IF(
                                    MA.DATE_MAINT IS NOT NULL,
                                    "A Réhabiliter",
                                    "Non Habilité"
                                ),
                                IF(
                                    MA.DATE_MAINT IS NOT NULL
                                    AND DATEDIFF( NOW(), MA.DATE_MAINT ) < H.DELAIS-H.AJUSTEMENT,
                                    IF(
                                        MA.PARTIEL = 1,
                                        "Habilité Partiellement",
                                        "Habilité"
                                    ),
                                    IF(
                                        MA.DATE_MAINT IS NOT NULL
                                        AND DATEDIFF( NOW(), MA.DATE_MAINT ) BETWEEN H.DELAIS-H.AJUSTEMENT AND H.DELAIS+H.AJUSTEMENT,
                                        "A Maintenir",
                                        IF(
                                            MA.DATE_MAINT IS NOT NULL
                                            AND DATEDIFF( NOW(), M.DATE_MAINT ) > H.DELAIS+H.AJUSTEMENT,
                                            "Dépassé",
                                            IF(
                                                MA.DATE_MAINT IS NULL
                                                AND (
                                                    HA.DATE_FORM IS NOT NULL
                                                    OR HA.VAE = 1
                                                ),
                                                "Formation",
                                                "Non Habilité"
                                            )
                                        )
                                    )
                                )
                            )
                        ) AS statut
                    FROM
                        cybele_secteur_agent SA
                            CROSS JOIN cybele_cat_hab H
                            INNER JOIN members M
                                ON M.id = SA.code_agent
                            LEFT JOIN cybele_hab_agent HA
                                ON SA.CODE_MEMBERS = HA.CODE_MEMBERS
                                AND H.CODE_CAT_HAB = HA.CODE_CAT_HAB
                            LEFT JOIN (
                                    SELECT CODE_MEMBERS, MAX( DATE_SUSP_AGENT ) max_date
                                    FROM cybele_agent_susp
                                    GROUP BY CODE_MEMBERS
                                ) MS
                                ON SA.CODE_MEMBERS = MS.CODE_MEMBERS
                            LEFT JOIN cybele_agent_susp ASU
                                ON MS.CODE_MEMBERS = ASU.CODE_MEMBERS
                                AND MS.max_date = ASU.DATE_SUSP_AGENT
                            LEFT JOIN (
                                    -- Dernier maintient par agent
                                    SELECT CODE_MEMBERS, CODE_CAT_HAB, MAX( DATE_MAINT ) AS max_date
                                    FROM cybele_maint_agent
                                    GROUP BY CODE_MEMBERS, CODE_CAT_HAB
                                ) MMA
                                ON SA.CODE_MEMBERS = MMA.CODE_MEMBERS
                                AND H.CODE_CAT_HAB = MMA.CODE_CAT_HAB
                            LEFT JOIN cybele_maint_agent MA
                                ON MMA.CODE_MEMBERS = MA.CODE_MEMBERS
                                AND MMA.CODE_CAT_HAB = MA.CODE_CAT_HAB
                                AND MMA.max_date = MA.DATE_MAINT
                    -- La clause WHERE sera facultative si tu veux tous les secteurs
                    WHERE
                        SA.CODE_SECTEUR = 'id secteur souhaité'
                        AND H.CODE_SECTEUR = 'id secteur souhaité'
                    ORDER BY 1, 2, 3

                    J'ai repris la structure de tes IF imbriqués pour déterminer le statut.

                    Cela va te retourner un tableau droit du genre :

                    CODE_SECTEURCODE_MEMBERSNOMPRENOMCODE_CAT_HABACRONYMESTATUT
                    1 1 Jean Claude 1 A Non habilité
                    1 2 Jean Pierre 1 A Non habilité
                    1 1 Jean Claude 2 B Habilité
                    1 2 Jean Pierre 2 B Non habilité
                    2 1 Jean Claude 1 A Non habilité
                    2 2 Jean Pierre 1 A Non habilité

                    Et c'est côté application que tu va "croiser" cela pour obtenir ton résultat d'affichage souhaité ...

                    -
                    Edité par Benzouye 9 mai 2019 à 17:32:38

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

                      Effectivement, au moment de faire porter la mise en forme de mon tableau par le sql, je me suis dis que cela n'était pas le cadre idéal de développement... et je me suis douté que dans un futur plus ou moins proche, il faudrait remettre ce code d'aplomb :D

                      Mais tout fonctionnait si bien !

                      Je teste ton code demain et réadapterai mon php, merci pour ton investissement !

                      Up 10/05 - 08:47

                      Bonjour,

                      J'ai testé ta requête ce matin, elle fonctionne.

                      Ma première question est :

                      Pourquoi faire un CROSS JOIN plutôt qu'un INNER JOIN avec une jointure sur le code secteur ?

                      Dans ma proposition le produit cartésien serait alors réduit aux bonnes associations alors que dans le CROSS JOIN j'ai des habilitations pour des secteurs ou agents inconnus. Je pourrai cependant tout de même adapter mes statuts pour avoir un item "NON CONCERNE" mais est-ce plus adapté? performant ?

                      Ma deuxième question est :

                      Si j'ai initialement formater mes données avec le sql c'est que je suis plus "à l'aise" avec ce langage qu'avec le php.

                      Aurais tu une piste pour m'orienter sur la façon de parcourir ce tableau droit en php est de formater ma matrice ?

                      Une solution serait de parcourir le tableau droit trié et à chaque changement d'item habilitation de créer une nouvelle colonne mais alors comment savoir si je suis sur la bonne ligne agent ? D’où l’intérêt d'un CROSS JOIN exhaustif et d'être du coups sûr d'être à la bonne position dans le tableau ?

                      Up 10/05 - 11:59

                      Voici un bout de php pour exploiter la requête que tu m'as fournis, j’espère ne as monter une usine à gaz et me fier à l'ordre d'apparition des données me fait un peu peur non ?

                      mais peut-être que cela n'est pas dans ton domaine de compétence ? auquel cas je me tournerai vers un forum dédié.

                      $Agent='';
                              $Habilitation='';
                              $StatutHabAgent='';
                              $ListeHabilitation='<tr><td>QUI</td>';
                              $nb=0;
                              foreach ($resreqMatrice as $HabAgent) 
                              {
                                  if($Agent!=$HabAgent['CODE_AGENT'] and $Agent!='')
                                  {
                                      $nb++;
                                  }
                                  if($Agent!=$HabAgent['CODE_AGENT'])
                                  {
                                      if($Agent!='')
                                      {
                                          $StatutHabAgent=$StatutHabAgent.'</tr>';
                                      }
                                      $StatutHabAgent=$StatutHabAgent.'<tr><td>'.$HabAgent['NOM'].' '.$HabAgent['PRENOM'].'</td><td>'.$HabAgent['statut'].'</td>';
                                  }
                                  else
                                  {
                                      $StatutHabAgent=$StatutHabAgent.'<td>'.$HabAgent['statut'].'</td>';
                                  }
                                  
                                  if($nb==0)
                                  {
                                      $ListeHabilitation=$ListeHabilitation.'<td>'.$HabAgent['ACRONYME'].'</td>';
                                  }
                                  $Agent=$HabAgent['CODE_AGENT'];
                                  $Habilitation=$HabAgent['ACRONYME'];
                              }
                              $StatutHabAgent=$StatutHabAgent.'</tr>';
                              $ListeHabilitation=$ListeHabilitation.'</tr>';
                              
                              $matrice='<table>
                              <caption>Matrice des habilitations (';
                              $reqLibSect=get_secteur($_SESSION['Secteur']);
                              while($resreqLibSect=$reqLibSect->fetch())
                              {
                                  $matrice=$matrice.$resreqLibSect['LIBELLE_SECTEUR'].' ';
                              }
                              $matrice=$matrice.') </caption>
                              <thead>';   
                              $matrice=$matrice.$ListeHabilitation;
                              $matrice=$matrice.'</thead><tbody>';
                              $matrice=$matrice.$StatutHabAgent;
                              $matrice=$matrice.'</tbody></table>';


                      le produit cartésien me doublonne les réponses pour les agent ayant plusieurs secteurs.

                      UP 10/05/2019 15:26

                      Je me demande si mettre en place les intégrités référentielles vaut le coup, je vient de lire dans la doc mysql que le moteur myisam ne le supporte pas contrairement à innoDB et que leur mise  en place n'est pas toujours souhaitable, ce qui me surprend  beaucoup... qu'en penses tu ?

                      -
                      Edité par guismo667 10 mai 2019 à 15:28:16

                      • Partager sur Facebook
                      • Partager sur Twitter

                      [MySQL-5.7] SQL et performances contre intuitive

                      × 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