Regroupement / Calcul nombre d’occurrences

Petit nouveau ! | 9 Messages

08 oct. 2013, 19:48

Bonjour,

Je travaille actuellement sur une solution en PHP afin de réaliser un taux de retour dynamique.

Dans une BDD phpMyAdmin, voici le décor :

Il y a un champs "Segments" qui peut avoir un nombre et un type de valeur indéfini. Comme par exemple : A, B, C, AAA, ABC, A1H ...
Il y a un champs "Completed" qui a pour valeur 1 ou 0, suivant qu'une action ait été complétée ou pas (0 = incomplète / 1 = complète)

Ce qui équivaut par exemple, à avoir un tableau de la sorte :

Image

J'aimerai afficher pour chacun des segments, le nombre total d’occurrences ainsi que le nombre de tag Completed égal à 1 et enfin calculer le taux de retour.

Comme ceci :

Image

Pourriez vous m'aiguiller à savoir comment il faut faire s'il vous plait pour générer ce tableau s'il vous plait ?

J'ai créé une double boucle pour ce faire, mais les résultats ne s'affichent pas correctement :

Voici mon code :
		<?php
		try
		{
			// On se connecte à MySQL
			$bdd = new PDO('mysql:host=localhost;dbname=test', 'root', '');
		}
		catch(Exception $e)
		{
			// En cas d'erreur, on affiche un message et on arrête tout
			die('Erreur : '.$e->getMessage());
		}
			//Requete de selection
			
				$tableau_segment = $bdd->query('SELECT Segment, COUNT(*) FROM return_rate_2 GROUP BY Segment');
				
				while ($Group_Segment = $tableau_segment ->fetch())

				{
		?>
				<div>
				<?php 
				echo $Group_Segment['Segment']; ?> -
				<?php
				echo $Group_Segment['COUNT(*)']; ?> -
				</div>
		<?php
				}
				$tableau_segment->closeCursor();

				$tableau_segment_1 = $bdd->query('SELECT COUNT(Completed) FROM return_rate_2 where Completed= 1 GROUP BY Segment');
				
				while ($Group_Segment_1 = $tableau_segment_1 ->fetch())

				{
		?>
				<div> 
				<?php
				echo $Group_Segment_1['COUNT(Completed)']; ?> -
				</div>
		<?php
				}
				$tableau_segment_1->closeCursor();
		
		?>
Et voici le résultat de mon code :

Image

Le nombre de tag à 1 par segment ce situe sous les segments A, B, C.

Merci d'avance pour votre aide !

N'hésitez pas à revenir vers moi si je ne suis pas clair.

Alexandre

ViPHP
ViPHP | 928 Messages

08 oct. 2013, 21:14

Salut,
Le plus simple c'est de remplir d'abord un tableau en PHP pour ensuite l'afficher facilement.

En gros au final tu veux un tableau comme ceci :
$data = array(
   'A' => array('total' => 3, 'totalCompleted' => 2, 'rate' => 67),
   'B' => array('total' => 2, 'totalCompleted' => 2, 'rate' => 100),
   'C' => array('total' => 3, 'totalCompleted' => 1, 'rate' => 37),
);
L'algo donnerait un truc du genre (pas testé mais ça devrait marcher si ya pas de parse error :p) :
$data = array();

$stmt = $pdo->query('SELECT Segment, COUNT(*) as total FROM return_rate_2 GROUP BY Segment');
while ($row = $stmt ->fetch())
{
   $data[$row['Segment']] = array(
      'total' => $row['total'],
      'totalCompleted' => 0,
      'rate' => 0,
   );
}

$stmt = $pdo->query('SELECT COUNT(Completed) as totalCompleted FROM return_rate_2 where Completed= 1 GROUP BY Segment');
while ($row = $stmt ->fetch())
{
   $data[$row['Segment']]['totalCompleted'] = $row['totalCompleted'];
   $data[$row['Segment']]['rate'] = ($data[$row['Segment']]['totalCompleted'] * 100) / $data[$row['Segment']]['total']; // Taux en % = (totalCompleted * 100) / total
}

Et maintenant que $data contient tes données comme il faut, tu n'as plus qu'à le parcourir le plus simplement du monde :)

++

Petit nouveau ! | 9 Messages

16 oct. 2013, 15:41

Bonjour Genova,

Désolé pour ma réponse tardive, mais j'avais un peu la tête sous l'eau ces dernières semaines.

Je viens donc d'essayer le code que tu m'as envoyé, j'ai un Parse Error en ligne 45.

Je l'ai aussi un peu modifié comme suit :
		<?php
		try
		{
			// On se connecte à MySQL
			$bdd = new PDO('mysql:host=localhost;dbname=test', 'root', '');
		}
		catch(Exception $e)
		{
			// En cas d'erreur, on affiche un message et on arrête tout
			die('Erreur : '.$e->getMessage());
		}
		$data = array();
		
			//Requete de selection
			$boucle = $bdd->query('SELECT Segment, COUNT(*) as total FROM return_rate_2');
			while ($row = $boucle ->fetch())
			{
			   $data[$row['Segment']] = array(
				  'total' => $row['total'],
				  'totalCompleted' => 0,
				  'rate' => 0,
			   );
			}
		
			$boucle = $bdd->query('SELECT Segment, COUNT(Completed) as totalCompleted FROM return_rate_2 where Completed= 1 GROUP BY Segment');
			while ($row = $boucle ->fetch())
			{
			   $data[$row['Segment']]['totalCompleted'] = $row['totalCompleted'];
			   $data[$row['Segment']]['rate'] = ($data[$row['Segment']]['totalCompleted'] * 100) / $data[$row['Segment']]['total']; // Taux en % = (totalCompleted * 100) / total
			}

		?>
J'ai beau essayé de trouver une solution, je ne comprends pas pourquoi... Est ce que tu peux m'aider de nouveau à ce sujet s'il te plait ?

Merci d'avance !

Petit nouveau ! | 9 Messages

16 oct. 2013, 17:19

Pour information, la ligne 45 à laquelle je fais référence est la suivante :
$data[$row['Segment']]['rate'] = ($data[$row['Segment']]['totalCompleted'] * 100) / $data[$row['Segment']]['total']; // Taux en % = (totalCompleted * 100) / total
Voici les erreurs qui s'affichent :

Notice: Undefined index: total in C:\wamp\www\Projets\return_rate_12.php on line
Warning: Division by zero in C:\wamp\www\Projets\return_rate_12.php on line

Merci !

Alexandre

Petit nouveau ! | 9 Messages

21 oct. 2013, 09:17

Personne ?

Eléphant du PHP | 116 Messages

21 oct. 2013, 09:47

Salut,

J'ai pas lu tout les messages, mais as tu compris l'erreur ? En gros tu essayes de faire ta division avec un index qui n'existe pas (Notice), du coup il croit que tu veux diviser par zéro (Warning) et là : c'est le drame. As tu essayé de changer l'index ?
@+,
Computarelier

ViPHP
ViPHP | 2577 Messages

21 oct. 2013, 10:27

Bonjour,

Pourquoi ne pas faire :
SELECT Segment, COUNT(*) as total, SUM(Completed) as TotalCompleted FROM return_rate_2 group by Segment
Edit : Il manque le group by dans le premier select ce qui fait qu'il ne retourne qu'un segment (le dernier ?) et le nombre de ligne total de la table et non pas une ligne par segment.

Petit nouveau ! | 9 Messages

21 oct. 2013, 18:19

Hello,

Oui j'avais compris les messages d'erreur, cependant je n'avais pas compris comment on devait calculer 'rate' et 'totalCompleted'.

En rajoutant les calculs directement dans la requête de ces deux "index" (?), je comprends maintenant comment cela fonctionne.

Merci beaucoup pour ton aide, par contre je ne vois pas du tout comment afficher mon tableau maintenant...

Est ce que tu peux me donner un dernière coup de mains à ce sujet ?

Bien cordialement,

Alexandre

ViPHP
ViPHP | 2577 Messages

21 oct. 2013, 23:50

foreach ($row as $segment=>$data){ tu peux utiliser $data['rate'] et les autres }

Petit nouveau ! | 9 Messages

22 oct. 2013, 21:12

J'ai un parse error qui indique qu'il y a un un argument invalide dans foreach ($row as $segment=>$data).

Je pense que c'est du fait de $Segment, qui fait référence à un champ de ma BDD mais qui n'a pas été déclaré en tant que variable.

Comment peut on faire référence au champ segment et donc à A, B, C, etc comme si c'était une variable dans ce cas ?

Petit nouveau ! | 9 Messages

23 oct. 2013, 13:02

Quelqu'un peut m'aider ?!

ViPHP
ViPHP | 2577 Messages

23 oct. 2013, 13:18

Le message exact est plus utile pour comprendre.
Peux tu remettre ton code, parce que je ne sais pas ou tu en es et quels options tu as choisi parmi les idées proposées.

Petit nouveau ! | 9 Messages

23 oct. 2013, 14:01

Bonjour Mazarini,

Voici le code :
<?php
                try
                {
                        // On se connecte à MySQL
                        $bdd = new PDO('mysql:host=localhost;dbname=test', 'root', '');
                }
                catch(Exception $e)
                {
                        // En cas d'erreur, on affiche un message et on arrête tout
                        die('Erreur : '.$e->getMessage());
                }
                $data = array();
                
                        //Requete de selection
                        $boucle = $bdd->query('SELECT Segment, COUNT(*) as total, SUM(Completed) AS totalCompleted  FROM return_rate_2 GROUP BY Segment ');
                        while ($row = $boucle ->fetch())
                        {
                          $data[$row['Segment']] = array(
                                  'total' => $row['total'],
                                  'totalCompleted' => 0,
                                  'rate' => 0,
                           );
                        }
						$Segment = $row['Segment'];
						
                        $boucle = $bdd->query('SELECT Segment, COUNT(Completed) as totalCompleted FROM return_rate_2 where Completed= 1 GROUP BY Segment');
                        while ($row = $boucle ->fetch())
                        {
                            $total = $data[$row['Segment']]['totalCompleted'] = $row['totalCompleted'];
                            $taux = $data[$row['Segment']]['rate'] = ($data[$row['Segment']]['totalCompleted'] * 100) / $data[$row['Segment']]['total']; // Taux en % = (totalCompleted * 100) / total
                        }
				foreach ($row as $Segment=>$data)
				{
				echo $data['Segment'];
				echo $total;
				echo $data['totalCompleted'];
				echo $taux;
				}
				?>
Et le message exact : "SCREAM: Error suppression ignored for" et "Warning: Invalid argument supplied for foreach() in C:\wamp\www\Projets\return_rate_13.php on line 48"

ViPHP
ViPHP | 2577 Messages

23 oct. 2013, 14:17

Pour répondre strictement à ta question :
foreach ($data ar $Segment=>$ligne) {
   echo $Segment;
   echo $ligne['total'];
   echo $ligne['totalCompleted'];
   echo $ligne['rate'];
}
Pour répondre vraiment :
Le premier select retourne toutes les données (pas besoin du second)
Puisque tu n'a plus qu'un select, tu peux faire l'affichage en même temps de la lecture
Il faut comprendre le code que tu utilises

Petit nouveau ! | 9 Messages

23 oct. 2013, 14:58

Le deuxième select me sert à calculer le taux de réussite (Rate) et le nombre de Segment à 1.

Du coup ça fonctionne bien, sauf qu'au niveau de l'affichage ça donne ça :
A / 4 / 3 / 75 % - B / 4 / 4 / 100 %

Alors que je voudrais cette serie sur deux lignes (une ligne par segment), de cette manière :
A / 4 / 3 / 75 %
B / 4 / 4 / 100 %

Voici mon code :
		 <?php
                try
                {
                        // On se connecte à MySQL
                        $bdd = new PDO('mysql:host=localhost;dbname=test', 'root', '');
                }
                catch(Exception $e)
                {
                        // En cas d'erreur, on affiche un message et on arrête tout
                        die('Erreur : '.$e->getMessage());
                }
                $data = array();
                
                        //Requete de selection
                        $boucle = $bdd->query('SELECT Segment, COUNT(*) as total, SUM(Completed) AS totalCompleted  FROM return_rate_2 GROUP BY Segment ');
                        while ($row = $boucle ->fetch())
                        {
                          $data[$row['Segment']] = array(
                                  'total' => $row['total'],
                                  'totalCompleted' => 0,
                                  'rate' => 0,
                           );
                        }

                        $boucle = $bdd->query('SELECT Segment, COUNT(Completed) as totalCompleted FROM return_rate_2 where Completed= 1 GROUP BY Segment');
                        while ($row = $boucle ->fetch())
                        {
                            $data[$row['Segment']]['totalCompleted'] = $row['totalCompleted'];
                            $data[$row['Segment']]['rate'] = ($data[$row['Segment']]['totalCompleted'] * 100) / $data[$row['Segment']]['total']; // Taux en % = (totalCompleted * 100) / total
                        }


				?>
				<?php
					foreach ($data as $Segment=>$row) {
							echo $Segment;
							echo $row['total'];
							echo $row['totalCompleted'];
							echo $row['rate'];
					}
				?>
PS : dsl pour toutes ces questions, mais je suis vraiment débutant et c'est compliqué pour moi...