Récup valeurs du jour courant au cours des années PHP-MySQL
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
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.
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
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.
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
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 ;-)
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.
Pas de quoi ;-)
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?
Ça devrait fonctionner en effet, je ne relève en tous cas rien d'incongru ;-)