Récup valeurs du jour courant au cours des années PHP-MySQL

Rechercher

Récup valeurs du jour courant au cours des années PHP-MySQL

Par papy71  -  9 reponses  -  Le 20/09/2019 15:13  -  Editer  - 

Bonjour à tous,
je peaufine mon programme en php 7, MySQL, GPgraph...
Dans ma base, j'ai une table avec des valeurs sur 10 ans.
Par requête je sais récupérer le max du mois courant par année, mais:

  • je n'arrive pas à récupérer la valeur dans chaque année pour la veille du jour courant.( Table mise à jour à 23h58 avec une tâche planifiée)

Afin de mieux comprendre voici le résultat avec ce lien:http://pv-solaire.alwaysdata.net/Compare_mois_an.php

Voici ma requête qui fonctionne avec les Max du mois courant par année.

    $tableauMois = array();  
    $tableauTotal_an = array();  
    $m1 = Date("m"); // trouve le mois courant  

    try{  

     $reponse = $bdd->prepare("SELECT  Total_an,Date FROM Retour   
       JOIN (select MAX(Date)AS maxDate FROM  Retour WHERE MONTH (Date)= $m1  
        GROUP BY YEAR( Date )) as valeur  
        ON Date=valeur.maxDate");  
            $reponse->execute();  
            $recois = $reponse->fetchAll();  

    }  

     catch (PDOException $e)  
     {  
      // en cas d'erreur dans la requete  
        echo "<br>Erreur : ".$e->getMessage();  
     }  

    foreach($recois as $R )  
     {  
     // Alimentation des tableaux  
        $tableauMois[] =  $R['Date'];  
        $tableauTotal_an[] = (float)$R['Total_an'];    
      }  

    $reponse->closeCursor(); // Termine le traitement de la requête  

    // affiche à l'écran le résultat des 2 tableaux  
    printf('<pre>%s</pre>', print_r($tableauTotal_an,1));  
    printf('<pre>%s</pre>', print_r($tableauMois,1));  

J'ai fais plusieurs essais, mais soit la requête est pas bonne, soit problème au niveau du foreach.
Je passe: $m1 = Date("m'-'d"); mon format de date est Y-m-d dans ma table.

Évidement j'avais plus les Max dans ma requête.
problème entre Year et Month peut être Day ?

Une autre solution?, fort possible car mes connaissances en MySQL sont limitées. Pour trouver les Max du mois par années, j'ai pas mal cherché, je ne trouvais que les Max des 12 mois par année.
Le but est que lorsque je visite la page, je veux comparer les valeurs de la veille dans les autres années, puis les voir en histogramme.

Merci pour l'aide.
Cordialement.
Guy

 

Réponses apportées à cette discussion

Par Cyrano  -  Le 29/09/2019 10:13  -  Haut de page  - 

Bonjour Guy,
je suis enclin à penser que le problème vient de la requête.

Mais pour en être sûr, il faudrait que j'aie une idée de la structure de la table Retour. Je suis en particulier curieux de comprendre ce qu'enregistre la colonne Total_an : est-ce que c'est une valeur calculée et enregistrée au fur et à mesure ?
Est-ce dans cette table existe une valeur quotidienne pour chaque date ?

En fonction de ces information, il faudra revoir la manière de formuler la requête, et ça risque d'être beaucoup plus complexe. De ce que je comprends, l'histogramme affiche des calculs par année à partir du 1er janvier de chaque année jusqu'à la date du jour, donc, pour l'exemple montré ici, du 1er janvier au 29 septembre pour chacune des année : s'il existe une colonne avec la valeur quotidienne, ce sera sans doute plus simple.

 
Par papy71  -  Le 29/09/2019 22:13  -  Haut de page  - 

Bonjour Cyrano,
Merci pour l'aide.
Concernant mon tableau:
les années vont du 1 septembre 2010 a ce jour et prévu pour 25 ans.
les champs sont:
Id, Date, Total_an, Total_mois, PV

chaque jour, avec une tâche planifiée, j'enregistre vers minuit la production du jour (PV). Puis un programme PHP fait le calcul en ajoutant ce nombre (PV) pour Linky, Total_an, Total_mois,et indique la date.
le 1 de chaque mois,nous repartons de zéro.
Edem pour le 1 janvier.
Linky additionne au fil des jours.

j'aimerai, de temps en temps, par simple consultation connaître la production du jour par rapport au même mois des autres années et vérifier si l'indice Linky correspond à celui de mon compteur EDF.

Le lien ci-dessus donne le résultat que je souhaite, mais je le fais manuellement.

Mais pour l'instant, avec le code ci-dessus j'ai ceci:
http://pv-solaire.alwaysdata.net/histo_mois.php
Je compare la production du jour-mois courant (si je le choisi le mois courant) avec la production totale du même mois des autres années.
Par contre ce code permet un regard entre les mêmes mois du choix de la liste déroulante.

Je pense que je réponds a votre demande.
Merci Cyrano

 
Par Cyrano  -  Le 30/09/2019 09:50  -  Haut de page  - 

Bonjour Guy,
ce n'est pas très clair, mais je vais tenter de reformuler pour être sûr de ce que j'ai compris.

Deux observations préalables :

  • la table comporte une colonne avec un nom réservé (Date) : il serait prudent de renommer cette colonne. Je n'ai jamais ce genre de problème parce que je rajoute toujours un suffixe « xxx » au nom des tables, suffixe que j'utilise par la suite comme préfixe pour le nom des colonnes. Par exemple ici, la table s'appelant « Retour » serait renommée « retour_ret », et les colonnes deviendraient ret_id, ret_date, ret_total_an, ret_total_mois et ret_pv, tout ça en minuscule. J'ajoute que ça offre un avantage pour les jointures, on sait de quelle table vient quelle colonne plus facilement, d'autant que si j'ai une clé étrangère, elle reprend le nom de sa table d'origine, préfixe inclus.
  • En principe, on ne stocke jamais de valeurs calculées dans une base de données, donc les colonnes total_an et total_mois ne devraient pas exister. Mais c'est là un détail sans grande incidence.

Si j'ai correctement suivi, les informations recherchées doivent servir à construire des histogrammes permettant de comparer la consommation d'une année sur l'autre pour une période données, à savoir pour une journée, ou bien pour un mois, ou bien pour une année à partir du 1er janvier. Formulé autrement, on doit pouvoir comparer les consommations du 29 septembre de chaque année, ou bien du mois de septembre de chaque année, ou bien enfin de l'ensemble de chaque année.


Je n'ai pas de jeu d'essai pour tester la requête, mais on pourrait avoir quelque chose comme ceci :

Pour la comparaison entre période annuelle, donc du 1er janvier à la date du jour, en prenant en compte que si je prend comme base la période entre le 1er janvier et la date courante de l'année en cours, je dois calculer la même période pour les années précédentes. On va paramétrer la requête (ce sont aussi des requêtes à exécuter avant la requête de collecte des informations :

    -- Définition de variables pour construire dynamiquement une date  
    SET @p_annee = 2019;  
    SET @p_mois  = '09';  
    SET @p_jour  = '30';  

    -- Requête pour récupérer un total annuel entre le 1er janvier et une date donnée de l'année quelle que soit l'année  
    SELECT  
      SUM(PV)       AS Total_an,
      CONCAT(  
        YEAR(Date),  
        '-',  
        @p_mois,  
        '-',  
        @p_jour  
      ) AS 'Date'  
    FROM Retour  
    WHERE Date BETWEEN CAST(CONCAT(YEAR(Date), '-01-01') AS DATE)
                   AND CAST(CONCAT(YEAR(Date), '-', @p_mois, '-', @p_jour) AS DATE)
    GROUP BY YEAR(Date)
    ORDER BY YEAR(Date);

À noter, l'utilisation de la fonction SQL CAST pour forcer un type : ici, la fonction CONCAT construit une chaîne de caractère dynamique, et CAST va indiquer que le résultat est de type DATE, ce qui permettra une comparaison SQL entre dates

Si je veux uniquement les chiffre des mois de septembre pour chaque année, je vais modifier comme suit (pas de changement pour les paramètres des lignes avec SET ... :

    SELECT  
      SUM(PV)       AS total_mois,  
      CONCAT(  
        YEAR(Date),  
        '-',  
        @p_mois,  
        '-',  
        @p_jour  
      ) AS 'Date'  
    FROM Retour  
    WHERE Date BETWEEN CAST(CONCAT(YEAR(Date), '-', @p_mois, '-01') AS DATE)  
                   AND CAST(CONCAT(YEAR(Date), '-', @p_mois, '-', @p_jour) AS DATE)  
    GROUP BY YEAR(Date)  
            ORDER BY YEAR(Date);  

Enfin, je peux comparer les chiffres du 30 septembre pour chaque année beaucoup plus simplement ainsi (toujours en gardant les paramètres) :

    SELECT  
      PV            AS total_jour,  
      CONCAT(  
        YEAR(Date),  
        '-',  
        @p_mois,  
        '-',  
        @p_jour  
      ) AS 'Date'  
    FROM Retour  
    WHERE Date = CAST(CONCAT(YEAR(Date), '-', @p_mois, '-', @p_jour) AS DATE)  
    ORDER BY YEAR(Date);  

Tout ceci est à tester bien entendu, et on relève au passage que dans aucune de ces requêtes je n'utilise les colonnes Total_an ou Total_mois, valeurs calculées qui se révèlent en l'occurrence un peu inutiles tant qu'on fait des comparaisons incluant l'année en cours qui n'est pas terminée.

S'il y a des erreurs, il faudra m'en indiquer le libellé exact.

 
Par papy71  -  Le 14/10/2019 17:48  -  Haut de page  - 

Bonjour Cyrano,

Mes excuses, j'ai été beaucoup occupé par mon association, c'est les demandes de subvention, donc a ne pas négliger.... ;-)

Je viens de reprendre votre programme et je l'ai adapter pour ma table. par exemple au dernier jour d'enregistrement soit la veille du jour courant. (votre dernier programme)

    <?php  

    require_once ('Connect.php'); // connexion à ma Base  

    //-- Définition de variables pour construire à la date d'hier.    
        $p_annee = DATE('Y');    
        $p_mois  = DATE('m');    
        $p_jour  = DATE('d');  
        $p_jour  = $p_jour -1; // pour avoir la date d'hier   

    // requête sur vos conseilles  

        $reponse = $bdd->prepare("SELECT    
          PV AS total_jour,    
          CONCAT(    
            YEAR(Date),    
            '-',    
            $p_mois,    
            '-',    
            $p_jour    
          ) AS 'Date'    
        FROM Retour    
        WHERE Date = CAST(CONCAT(YEAR(Date), '-', $p_mois, '-', $p_jour) AS DATE)    
        ORDER BY YEAR(Date)");   
        $reponse->execute();  
        $recois = $reponse->fetchAll();  

        foreach($recois as $R )  
     {  
        // Alimentation des tableaux de données  
        $tableauDate[] =  $R['Date'];  
        $tableauTotal_mois[] = (float)$R['total_jour'];    
      }  
       $reponse->closeCursor(); // Termine le traitement de la requête  

        printf( '<pre>%s</pre>', print_r( $tableauDate, 1 ) );  
        printf( '<pre>%s</pre>', print_r( $tableauTotal_mois, 1 ) );  
    ?>  

Parfait, j'ai bien les valeurs du même jour pour chaque année.
voici le résultat, nous sommes le 14 octobre donc affichage du 13.

    Array  
    (  
        [0] => 2010-10-13  
        [1] => 2011-10-13  
        [2] => 2012-10-13  
        [3] => 2013-10-13  
        [4] => 2014-10-13  
        [5] => 2015-10-13  
        [6] => 2016-10-13  
        [7] => 2017-10-13  
        [8] => 2018-10-13  
        [9] => 2019-10-13  
    )  

    Array  
    (  
        [0] => 10  
        [1] => 6  
        [2] => 8  
        [3] => 7  
        [4] => 6  
        [5] => 7  
        [6] => 1  
        [7] => 8  
        [8] => 9  
        [9] => 8.91  
    )  

Maintenant, pour l'obtention des autres comparaisons, il me reste à adapter en fonction d'une liste box et passer des variables.
Vrai que sur ma table j'économise pas mal d'octets sur 10 ans déjà et pour les années futures.

Merci encore Cyrano, et j'ose pas dire à la prochaine fois...
Cordialement.
Guy

 
Par Cyrano  -  Le 14/10/2019 18:36  -  Haut de page  - 

Attention : si nous sommes le premier du mois, il va y avoir un soucis :

Il faudrait adapter un peu le code pour prévoir ce cas de figure. Si on est le premier du mois, moins 1 => le zéro. Selon le mois, il faut donc calculer la date du dernier jour du mois précédent, il faut retirer 1 au mois, et pour le cas où on serait en janvier, il faudrait aussi retrancher 1 à l'année.

Dans l'immédiat, je vous laisse méditer la question, revenez si vous bloquez ;-)

 
Par papy71  -  Le 15/10/2019 10:13  -  Haut de page  - 

Ouff, effectivement, je suis resté dans le code sans réfléchir plus loin.

Avec des conditions, cela semble simple à remédier ces problèmes, je vais regarder.

Vous avez l'oeil, Cyrano, merci.

 
Par Cyrano  -  Le 15/10/2019 10:16  -  Haut de page  - 

Pas de quoi ;-)

 
Par papy71  -  Le 15/10/2019 19:48  -  Haut de page  - 

Je reviens pour résoudre le cas du 1er de chaque mois de de l'année.
J'ai commencer pour les années avec une condition:

    if ($DATE == DATE('Y-01-01') ){  
        $p_mois = '12';  
        $p_jour = '31';  
        $p_annee = $p_annee - 1;  
    }

Mais il y a plus simple, du moins je pense pour résoudre tous les cas.

Dans mes variables:

$p_annee = DATE('Y'); $Y = $p_annee; 
$p_mois  = DATE('m'); $m = $p_mois; 
$p_jour  = DATE('d'); $d = $p_jour;

// soustration d'un jour  
$date = new DateTime ( $Y.'-'.$m.'-'.$d );  
$date -> sub (new DateInterval ( 'P1D' ));  
echo $date -> format ( 'Y-m-d' ) . "\n" ;   

Dans ce cas, plus de problème et c'est plus simple.
Est-ce bon ainsi?

 
Par Cyrano  -  Le 15/10/2019 19:55  -  Haut de page  - 

Ça devrait fonctionner en effet, je ne relève en tous cas rien d'incongru ;-)

 

Ajouter une réponse à la discussion

Seuls les membres connectés sont autorisés à poster dans les forums !

Identifiez-vous
Join |  ID/MDP? |