Partage
  • Partager sur Facebook
  • Partager sur Twitter

Boucler sur des requêtes? bonne idée?

Comment éviter de faire une boucle sur des requêtes?

Sujet résolu
    7 juillet 2022 à 18:59:43

    Bonjour, je suis à la recherche d'une idée pour éviter de créer un boucle sur des requêtes, il me semble bien me souvenir qu'on me l'a déconseillé...

    J'ai actuellement un code qui calcul des delta de mesures de poids pour une ruche, sur une période donnée (1 jour, 2 jour ,3 jours, 1 semaine,...) j'aurais aimé avoir la possibilité de le faire sur une page de synthèse pour l'ensemble de mes ruches...

    Cela fonctionne très bien pour une seule ruche quel qu'elle soit , mais je suis un peu coincé sur l'idée de réaliser une boucle au niveau des requêtes pour permettre l'acquisition et l'affichage des autres ruches.. 

    Un regard neuf (à moins qu'il n'y a pas d'autres choix, ou alors encore une modification de requête hors de ma portée...)

    <!DOCTYPE HTML>
    <!--
    	Editorial by HTML5 UP
    	html5up.net | @ajlkn
    	Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
    	https://zestedesavoir.com/tutoriels/351/paginer-avec-php-et-sql/
    -->
    <html lang="fr">
    
    	<head>
    		<title>Suivi données des ruches de Gilles </title>
    		<meta charset="utf-8" />
    		<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
    		<link rel="stylesheet" href="assets/css/main.css" />
    		<link rel="stylesheet" href="assets/css/mon_css.css" />
    		<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js"></script>
    		
    	</head>
    	
    	<body class="is-preload">
    	<h1> <span style ="color:green";>Les ruches de Gilles </span></h1>		<!-- Titre de la page centré  via main.css-->
    	<h2> <span style ="color:red";>Delta de toutes les ruches!</span></h2>
    	
    		<!-- Wrapper -->
    			<div id="wrapper">
    
    				<!-- Main -->
    					<div id="main">
    						<div class="inner">
    
    							<!-- Header -->
    								<header id="header">
    									<a href="index.php" class="logo"><b>Accueil</b></a>
    
    								</header>
    
    							<!-- Content -->
    								<section>
    									<header class="main">
    					<h4><div><b>Nous sommes le <span id="heure_exacte"></span></b></div> 	</h4>
    					
    					<span class="image main">
    					<img src="images/rucherpam.png" alt="" title ="Delta Ruches"  style="margin-left: auto; margin-right: auto;" />
    					</span>	
    								
    						</header>
    												
    
    
    										
    										
    
    <script>
    
    
    window.onload = function() {
    setInterval("dateEtHeure()", 1000);
    							};
    
    							
    </script>
    				
    			
    				
    									
    
    <?php
    error_reporting(E_ALL);
    ini_set('display_errors', TRUE);
    ini_set('display_startup_errors', TRUE);
    
    /* Connexion à une base MySQL avec l'invocation de pilote */
    $dsn = 'mysql:dbname=ruches;host=127.0.0.1';
    $user = 'user';
    $password = 'password';
    
    
    try {
        $bdd = new PDO($dsn, $user, $password);
    // Activation des erreurs PDO
     $bdd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
    // mode de fetch par défaut : FETCH_ASSOC / FETCH_OBJ / FETCH_BOTH
    
     $bdd->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
    } catch (PDOException $e) {
        echo 'Connexion échouée : ' . $e->getMessage();
    }
    
          // Liste de toutes les ruches
        $requete1 = $bdd->query('SELECT * FROM Liste_ruches');
        $ruches = $requete1->fetchAll();
    	
    
    $NumRuche=1;		
    
    // ON attaque les requêtes pour les DELTA!
    
    //Mesure la plus récente
    $reponse0 = $bdd->query("SELECT DATE_FORMAT(horodatage, '%d/%m/%Y %Hh%i') AS date_formatee, mas FROM Telemesures_ruches
    WHERE id_ruche = $NumRuche AND horodatage >= NOW() - INTERVAL 1 WEEK ORDER BY horodatage DESC LIMIT 1");
    
    $donnees0 = $reponse0->fetch();
    $reponse0->closeCursor();
    
    //Mesure il y a un jour 
    $reponse1 = $bdd->query("SELECT DATE_FORMAT(horodatage, '%d/%m/%Y %Hh%i') AS date_formatee, mas FROM Telemesures_ruches
    WHERE id_ruche = $NumRuche AND horodatage >= NOW() - INTERVAL 1 DAY ORDER BY  horodatage ASC LIMIT 1");
    
    $donnees1 = $reponse1->fetch();
    $reponse1->closeCursor();
    
    //Mesure il y a deux jours
    $reponse2 = $bdd->query("SELECT DATE_FORMAT(horodatage, '%d/%m/%Y %Hh%i') AS date_formatee, mas FROM Telemesures_ruches
    WHERE id_ruche = $NumRuche AND horodatage >= NOW() - INTERVAL 2 DAY ORDER BY horodatage ASC LIMIT 1");
    
    $donnees2 = $reponse2->fetch();
    $reponse2->closeCursor();
    
    //Mesure il y a trois jours
    $reponse3 = $bdd->query("SELECT DATE_FORMAT(horodatage, '%d/%m/%Y %Hh%i') AS date_formatee, mas FROM Telemesures_ruches
    WHERE id_ruche = $NumRuche AND horodatage >= NOW() - INTERVAL 3 DAY ORDER BY horodatage ASC LIMIT 1");
    
    $donnees3 = $reponse3->fetch();
    $reponse3->closeCursor();
    
    //Mesure  il y a une semaine
    $reponse4 = $bdd->query("SELECT DATE_FORMAT(horodatage, '%d/%m/%Y %Hh%i') AS date_formatee, mas FROM Telemesures_ruches
    WHERE id_ruche = $NumRuche AND horodatage >= NOW() - INTERVAL 1 WEEK ORDER BY horodatage ASC LIMIT 1");
    
    $donnees4 = $reponse4->fetch();
    $reponse4->closeCursor();
    
    //Mesure il y a deux semaines
    $reponse5 = $bdd->query("SELECT DATE_FORMAT(horodatage, '%d/%m/%Y %Hh%i') AS date_formatee, mas FROM Telemesures_ruches
    WHERE id_ruche = $NumRuche AND horodatage >= NOW() - INTERVAL 2 WEEK ORDER BY horodatage ASC LIMIT 1");
    
    $donnees5 = $reponse5->fetch();
    $reponse5->closeCursor();
    
    //Mesure il y a trois semaines
    $reponse6 = $bdd->query("SELECT DATE_FORMAT(horodatage, '%d/%m/%Y %Hh%i') AS date_formatee, mas FROM Telemesures_ruches
    WHERE id_ruche = $NumRuche AND horodatage >= NOW() - INTERVAL 3 WEEK ORDER BY horodatage ASC LIMIT 1");
    
    $donnees6 = $reponse6->fetch();
    $reponse6->closeCursor();
    
    //Mesure la plus ancienne il y a un mois
    $reponse7 = $bdd->query("SELECT DATE_FORMAT(horodatage, '%d/%m/%Y %Hh%i') AS date_formatee, mas FROM Telemesures_ruches
    WHERE id_ruche = $NumRuche AND horodatage >= NOW() - INTERVAL 1 MONTH ORDER BY horodatage ASC LIMIT 1");
    
    $donnees7 = $reponse7->fetch();
    $reponse7->closeCursor();
    
    //Mesure il y a deux mois
    $reponse8 = $bdd->query("SELECT DATE_FORMAT(horodatage, '%d/%m/%Y %Hh%i') AS date_formatee, mas FROM Telemesures_ruches
    WHERE id_ruche = $NumRuche AND horodatage >= NOW() - INTERVAL 2 MONTH ORDER BY horodatage ASC LIMIT 1");
    
    $donnees8 = $reponse8->fetch();
    $reponse8->closeCursor();
    
    // calculs des deltas
    $result1 = $donnees0['mas']-$donnees1['mas'];		// calcul sur les dernieres 24h
    $result2 = $donnees0['mas']-$donnees2['mas'];		// calcul sur les dernieres 48h
    $result3 = $donnees0['mas']-$donnees3['mas'];		// calcul sur les dernieres 72h
    $result4 = $donnees0['mas']-$donnees4['mas'];		// calcul sur la semaine
    $result5 = $donnees0['mas']-$donnees5['mas'];		// calcul sur 2 semaines
    $result6 = $donnees0['mas']-$donnees6['mas'];		// calcul sur 3 semaines
    $result7 = $donnees0['mas']-$donnees7['mas'];		// calcul sur le mois
    $result8 = $donnees0['mas']-$donnees8['mas'];		// calcul sur 2 mois
    
    //affichage tableau delta
    
    ?>  
     
    <h3> Vue synthétique des deltas des ruches!</h3>
    
    <?php
    	// Si il y a des ruches et des mesures on affiche le tableau
        // Sinon on affiche un message "aucune données"
        if( count ($ruches) )  {
    	
    
    
    		
    
      
    ?>
        <table>
    
            <thead>
                <tr>
                    
    <?php
    echo  '<tr><th>';
            // Une entête de colonne par ruche
            foreach( $ruches as $ruche ) {
    ?>
                         <th> Delta <?=$ruche['nom'];?></th> <th>Poids <?= $ruche['nom']; ?></th>
    <?php
            			     }
    ?>
                                    </tr>
                                </thead>
    							
    							<tbody>
    <?php
    echo  '<tr><td>Point de référence actuel:</td><td>/</td><td>'.$donnees0['mas'].'Kg</td></tr>'; 
    echo  '<tr><td>Variation du poids sur les 24 dernières heures :</td><td>'.round($result1,2).'Kg</td><td>'.$donnees1['mas'].'Kg</td></tr>';
    echo  '<tr><td>Variation du poids sur les 48 dernières heures :</td><td>'.round($result2,2).'Kg</td><td>'.$donnees2['mas'].'Kg</td></tr>';
    echo  '<tr><td>Variation du poids sur les 72 dernières heures :</td><td>'.round($result3,2).'Kg</td><td>'.$donnees3['mas'].'Kg</tr>';
    echo  '<tr><td>Variation du poids sur la dernière semaine :</td><td>'.round($result4,2).'Kg</td><td>'.$donnees4['mas'].'Kg</td></tr>';
    echo  '<tr><td>Variation du poids sur les 2 dernières semaine :</td><td>'.round($result5,2).'Kg</td><td>'.$donnees5['mas'].'Kg</td></tr>';
    echo  '<tr><td>Variation du poids sur les 3 dernières semaine :</td><td>'.round($result6,2).'Kg</td><td>'.$donnees6['mas'].'Kg</td></tr>';
    echo  '<tr><td>Variation du poids sur le dernier mois :</td><td>'.round($result7,2).'Kg</td><td>'.$donnees7['mas'].'Kg</td></tr>';
    echo  '<tr><td>Variation du poids sur les 2 derniers mois :</td><td>'.round($result8,2).'Kg</td><td>'.$donnees8['mas'].'Kg</td></tr>';
    
    
    ?>
    
    
    </tbody>
    <tfoot>
    <?php
    echo '<tr><td></td></tr>';
    ?>
    </tfoot>
    </table>
    
    
    <?php
    
    
    
    	
    		
    							}  // fin du if il y a des ruches
    
    
    $requete1->closeCursor();
    $bdd=Null;
    
    ?>
    <!-- affichage du bouton remontée contenu dans mon_javascript et mon_css-->
    
    <div id="scrollUp">
    <a href="#top"title="Haut de page"><img src="images/to_top.png"/></a>
    </div>
    
    <!--Affichage menu -->								
    								
     <?php include "menu.php"; // rajout du menu	?>
     						</div>
    					</div>
     
    </section>
    
    <script src="assets/js/mon_javascript.js"></script> <!--fichier contenant mes fonctions javaScript-->
    
    	</body>
    </html>
    

    Voici le rendu actuel du code ci-dessus:



    Merci

    • Partager sur Facebook
    • Partager sur Twitter
      8 juillet 2022 à 19:51:43

      Bonjour,

      On peut imaginer une solution sans multiplier le nombre de requêtes en rajoutant l'id_ruche dans chacune des 8 requêtes.

      Exemple avec celle des deux derniers jours :

      SELECT
      	M.id_ruche,
      	DATE_FORMAT( M.horodatage, '%d/%m/%Y %Hh%i' ) AS date_formatee,
      	M.mas
      FROM
      	Telemesures_ruches M
      		INNER JOIN (
      				-- Date mini de mesure par ruche sur les deux derniers jours
      				SELECT
      					id_ruche,
      					MIN( horodatage ) min_date
      				FROM Telemesures_ruches
      				WHERE horodatage >= NOW() - INTERVAL 2 DAY
      				GROUP BY id_ruche
      			) D
      			ON M.id_ruche = D.id_ruche
      			AND M.horodatage = D.min_date
      ORDER BY M.id_ruche ASC;

      Du coup, on peut faire varier la valeur de l'intervalle pour calculer les 8 valeurs voulues dans une boucle. Quoi ? Une boucle ? Il n'y a que 8 valeurs, toujours connues, dans pas de problème à le faire ici, cela ne fera pas plus de requêtes que ce que tu fais déjà ...

      Et pour la dernière valeur :

      SELECT
      	M.id_ruche,
      	DATE_FORMAT( M.horodatage, '%d/%m/%Y %Hh%i' ) AS date_formatee,
      	M.mas
      FROM
      	Telemesures_ruches M
      		INNER JOIN (
      				-- Dernière mesure par ruche
      				SELECT
      					id_ruche,
      					MAX( horodatage ) max_date
      				FROM Telemesures_ruches
      				GROUP BY id_ruche
      			) D
      			ON M.id_ruche = D.id_ruche
      			AND M.horodatage = D.max_date
      ORDER BY M.id_ruche ASC;

      Côté PHP, il faut "juste" créer un tableau avec les intervalles voulus, et stocker les résultats dans un tableau pour faire une boucle PHP sur $ruches comme tu le fais déjà sur la page d'accueil :

      <!DOCTYPE HTML>
      <html lang="fr">
      	<head>
      		<title>Suivi données des ruches de Gilles </title>
      		<meta charset="utf-8" />
      		<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
      		<link rel="stylesheet" href="assets/css/main.css" />
      		<link rel="stylesheet" href="assets/css/mon_css.css" />
      		<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js"></script>
      	</head>
      	<body class="is-preload">
      		<h1><span style ="color:green";>Les ruches de Gilles </span></h1>
      		<h2><span style ="color:red";>Delta de toutes les ruches!</span></h2>
      		<div id="wrapper">
      			<div id="main">
      				<div class="inner">
      					<header id="header">
      						<a href="index.php" class="logo"><b>Accueil</b></a>
      					</header>
      					<section>
      						<header class="main">
      							<h4><b>Nous sommes le <span id="heure_exacte"></span></b></h4>
      							<span class="image main">
      								<img src="images/rucherpam.png" alt="" title ="Delta Ruches"  style="margin-left: auto; margin-right: auto;" />
      							</span>
      						</header>
      						<script>
      							window.onload = function() {
      								setInterval("dateEtHeure()", 1000);
      							};					 
      						</script>
      <?php
      	error_reporting(E_ALL);
      	ini_set('display_errors', TRUE);
      	ini_set('display_startup_errors', TRUE);
      	$dsn = 'mysql:dbname=ruches;host=localhost';
      	$user = 'user';
      	$password = 'password';
      
      	try {
      		$bdd = new PDO( $dsn, $user, $password );
      		$bdd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
      		$bdd->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
      	}
      	catch (PDOException $e) {
      		echo 'Connexion échouée : ' . $e->getMessage();
      	}
      	
      	// Liste de toutes les ruches
      	$requete = $bdd->query('SELECT * FROM Liste_ruches');
      	$ruches = $requete->fetchAll();
      	
      	// Tableau des intervalles pour delta
      	$intervalles = [
      		'les 24 dernières heures' => '1 DAY',
      		'les 48 dernières heures' => '2 DAY',
      		'les 72 dernières heures' => '3 DAY',
      		'la dernière semaine' => '1 WEEK',
      		'les 2 dernières semaines' => '2 WEEK',
      		'les 2 dernières semaines' => '3 WEEK',
      		'le dernier mois' => '1 MONTH',
      		'les 2 derniers mois' => '2 MONTH'
      	];
      	
      	//Mesure la plus récente par ruche
      	$requete = $bdd->query( '
      		SELECT
      			M.id_ruche,
      			DATE_FORMAT( M.horodatage, "%d/%m/%Y %Hh%i" ) AS date_formatee,
      			M.mas
      		FROM
      			Telemesures_ruches M
      				INNER JOIN (
      						-- Dernière mesure par ruche
      						SELECT
      							id_ruche,
      							MAX( horodatage ) max_date
      						FROM Telemesures_ruches
      						GROUP BY id_ruche
      					) D
      					ON M.id_ruche = D.id_ruche
      					AND M.horodatage = D.max_date
      		ORDER BY M.id_ruche ASC;'
      	);
      	$dernieres = $requete->fetchAll();
      	foreach( $dernieres as $derniere ) {
      		$tableau_final[$derniere['id_ruche']]['derniere'] = $derniere['mas'];
      	}
      	
      	// Boucle pour requête par intervalle
      	$deltas = array();
      	foreach( $intervalles as $libelle => $interval ) {
      		$requete = $bdd->query( '
      			SELECT
      				M.id_ruche,
      				DATE_FORMAT( M.horodatage, "%d/%m/%Y %Hh%i" ) AS date_formatee,
      				M.mas
      			FROM
      				Telemesures_ruches M
      					INNER JOIN (
      							-- Date mini de mesure par ruche sur les deux derniers jours
      							SELECT
      								id_ruche,
      								MIN( horodatage ) min_date
      							FROM Telemesures_ruches
      							WHERE horodatage >= NOW() - INTERVAL '.$interval.'
      							GROUP BY id_ruche
      						) D
      						ON M.id_ruche = D.id_ruche
      						AND M.horodatage = D.min_date
      			ORDER BY M.id_ruche ASC;'
      		);
      		$deltas = $requete->fetchAll();
      		foreach( $deltas as $delta ) {
      			$tableau_final[$delta['id_ruche']][$libelle] = $delta['mas'];
      		}
      	}
      ?>
      						<h3>Vue synthétique des deltas des ruches</h3>
      <?php
      	if( count( $ruches ) ) {
      ?>
      						<table>
      							<thead>
      								<tr>
      					 				<th></th>
      <?php
      		// Une entête de colonne par ruche
      		foreach( $ruches as $ruche ) {
      ?>
      									<th>Delta <?=$ruche['nom'];?></th>
      									<th>Poids <?= $ruche['nom']; ?></th>
      <?php
      		}
      ?>
      								</tr>
      							</thead>
      							<tbody>
      <?php
      		// Ligne pour le point de référence
      ?>
      								<tr>
      									<th>Point de référence actuel</th>
      <?php
      		foreach( $ruches as $ruche ) {
      ?>
      									<td>/</td>
      									<td><?= $tableau_final[$ruche['id_ruche']]['derniere']; ?></td>
      <?php
      		}
      ?>
      								</tr>
      <?php
      		// Une ligne de tableau par intervalle
      		foreach( $intervalles as $libelle => $interval ) {
      ?>
      								<tr>
      									<th>Variation du poids sur <?= $libelle; ?> :</th>
      <?php								
      			foreach( $ruches as $ruche ) {
      				$dernier = round( $tableau_final[$delta['id_ruche']]['derniere'], 2 );
      				$poids = round( $tableau_final[$delta['id_ruche']][$libelle], 2 );
      				$delta = $poids - $dernier;
      ?>
      									<td><?= $delta; ?> Kg</td>
      									<td><?= $poids; ?> Kg</td>
      <?php
      			}
      ?>
      								</tr>
      <?php
      		}
      ?>
      							</tbody>
      						</table>
      						<div id="scrollUp">
      							<a href="#top"title="Haut de page"><img src="images/to_top.png"/></a>
      						</div>
      <?php
      	}
      	include "menu.php";
      ?>
      					</section>
      				</div>
      			</div>
      		</div>
      		<script src="assets/js/mon_javascript.js"></script>
      	</body>
      </html>

      J'ai encore repris l'indentation et le balisage (surtout les fermantes à la fin), il faut vraiment que tu t'y mettes pour améliorer la lisibilité et justement voir les décalages ;)

      -
      Edité par Benzouye 8 juillet 2022 à 19:54:04

      • 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 juillet 2022 à 11:57:24

        Bonjour, merci je suis en train de passer mon code au vérificateur w3c (il me reste plus que la page donnees) il y avait effectivement pas mal de soucis... de truc obsolète de balises fermantes, de manque d'espace, de choses inutile,...

        Puis je regarde les indentations et ensuite ton code.

        J'aurais parié qu'il allait falloir malheureusement (pour moi) passer par des requêtes à jointure....

        Merci encore je te tiens au jus dès que j'attaque cette partie.

        A+

        Bien W3c me dit enfin que tout est bon pour toutes mes pages...

        Du coup j'ai testé ton code et il y a une erreur sur les lignes :

        $dernier = round( $tableau_final[$delta['id_ruche']]['derniere'], 2 );
                        $poids = round( $tableau_final[$delta['id_ruche']][$libelle], 2 );

        J'obtiens ceci comme message :



         En mettant ceci : cela semble fonctionner

                        $dernier = round( $tableau_final[$ruche['id_ruche']]['derniere'], 2 );
                        $poids = round( $tableau_final[$ruche['id_ruche']][$libelle], 2 );

        (remplacement $delta  par $ruche), il faut juste que je vérifie si les valeurs obtenues sont les bonnes!

        J'ai aussi arrondi l'affiche de $delta sinon pleins de chiffre.

        <td><?= round($delta,2); ?> Kg</td>

        et corrigé ceci : il y a avait 2 fois 2 semaines

        'les 3 dernières semaines' => '3 WEEK',

        un copié/collé "malheureux" faisait qu'il y avait 2 entrées dans le tableau avec le même nom.

        Enfin quelque chose de mon niveau qui fait que je peux un peu participer!

        Et pour finir (enfin je pense) il y avait une inversion dans la formule de calcul de $delta ,celle-ci semble cohérente avec la page donnees et ma calculatrice!

        $delta =  $dernier - $poids;



        Merci énormément!

        Voici le rendu final :

        -
        Edité par GillesMangin-Voirin 9 juillet 2022 à 13:53:56

        • Partager sur Facebook
        • Partager sur Twitter

        Boucler sur des requêtes? bonne idée?

        × 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