[RESOLU] Etablir le rang dans un classement

Eléphanteau du PHP | 19 Messages

15 oct. 2012, 11:14

Bonjour,

Je cherche à établir le rang pour l'afficher à la place de l'actuel $rang (qui est juste incrémenté) sous la forme :

Clt - Nom Prénom - Licence - Points
1 - DUBOIS Jean - 007 - 86
2 - ROBERT David - 3652 - 80
3 - DURAND Joel - 12548 - 76
4 - BERNARD thomas - 3025 - 73
- RICHARD Francis - 458 - 73
- POTIN Jean-Pierre - 7963 - 73
5 - NICOLAS Edward - 6584 - 71
etc

Code : Tout sélectionner

$sql = <<<SQL SELECT id_result, manifestation, type, titre, SUM(points) as points, licence, nom, prenom, id_joueur FROM resultats_opens_2012 INNER JOIN joueur ON resultats_opens_2012.licence = joueur.id_joueur WHERE resultats_opens_2012.type = "OP_FEM" GROUP BY licence ORDER BY points DESC, nom ASC SQL; $req = mysql_query($sql) or die('Erreur SQL !<br />'.$req.'<br />'.mysql_error()); $rang = 1; if(($data = mysql_fetch_array($req)) != NULL) { echo '<table width="500px">'."\n"; echo '<tr height="25" id="legend">'; echo '<td align="center"><b>Clt</b></td>'; echo '<td align="center"><b>Nom et Prénom</b></td>'; echo '<td align="center"><b>Licence</b></td>'; echo '<td align="center"><b>Points</b></td>'; echo '</tr>'."\n"; do { echo '<tr>'; echo '<td align="center">'.$rang++.'</td>'; echo '<td>&nbsp;&nbsp;'.$data['nom'].' '.ucfirst($data["prenom"]).'</td>'; echo '<td align="center">'.$data['licence'].'</td>'; echo '<td align="center">&nbsp;&nbsp;'.$data['points'].'</td>'; } while(($data = mysql_fetch_array($req)) != NULL); echo '</table>'."\n"; } else { echo '<div align="center"><h2>Aucunes joueuses dans ce clasement</h2></div>'; }
Merci d'avance pour vos pistes.

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

15 oct. 2012, 12:10

salut,

Si tu veux le faire en SQL pur tu peux tester les fonctions olap http://sqlpro.developpez.com/article/ol ... se-window/


@+
Il en faut peu pour être heureux ......

Eléphanteau du PHP | 19 Messages

15 oct. 2012, 17:02

J'ai bien regardé du côté de ton lien et écrit :

Code : Tout sélectionner

$sql = <<<SQL SELECT id_result, manifestation, type, titre, points, licence, nom, prenom, id_joueur RANK() OVER (PARTITION BY licence ORDER BY points DESC) AS Rang FROM resultats_opens_2012 INNER JOIN joueur ON resultats_opens_2012.licence = joueur.id_joueur WHERE resultats_opens_2012.type = "OP_FEM" SQL; $req = mysql_query($sql) or die('Erreur SQL !<br />'.$req.'<br />'.mysql_error());
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '() OVER (PARTITION BY...
Un problème de version de mySql ?

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

15 oct. 2012, 23:33

hum a priori pas implémenté chez mysql surtout :s (pas trouvé de doc récente :s).

la pour le coup te reste a faire une fonction perso qui réaliseras le traitement pour toi.

si tu n'as pas souvent d'entrée (ajout / modif) je te conseillerais une colonne en plus avec le rang et un trigger qui lance la mise a jour de cette colonne).

ceci dit s'il ne s'agit que de l'affichage ta méthode est tout aussi efficace je pense.


@+
Il en faut peu pour être heureux ......

Eléphanteau du PHP | 19 Messages

16 oct. 2012, 15:41

pour le coup te reste a faire une fonction perso qui réaliseras le traitement pour toi.
Pourrais-tu développer un petit peu ?
je te conseillerais une colonne en plus avec le rang et un trigger qui lance la mise a jour de cette colonne
Est-ce que c'est possible de le faire en php ? ça m'a pas l'air simple ce "trigger" la mise à jour des rangs s'effectuerait quand ? lors de l'insertion d'un nouveau résultat ?

ViPHP
AB
ViPHP | 5818 Messages

16 oct. 2012, 18:51

C'est quoi ton problème ? Juste un problème d'affichage ?
Si oui pas besoin de s'embêter avec un trigger pour si peu dans le sens ou le traitement php est vraiment élémentaire. Si j'ai bien compris ton pb il te suffit d'enregistrer $data['points'] dans une variable, si la valeur suivante est différente, tu incrémente "rang", sinon tu ne l'incrémente pas.
Genre :
$rang = 0;
$points = -1; 
while(($data = mysql_fetch_array($req)) != NULL)
{
     $rang = $points != $data['points'] ? $rang++ : $rang ;
     $points = $data['points'];

      echo '<tr>';
      echo '<td align="center">'.$rang.'</td>';
      echo '<td>&nbsp;&nbsp;'.$data['nom'].' '.ucfirst($data["prenom"]).'</td>';
      echo '<td align="center">'.$data['licence'].'</td>';
      echo '<td align="center">&nbsp;&nbsp;'.$data['points'].'</td>';
      echo '</tr>';
}
Par sécurité tu devrais utiliser htmlspecialchars pour protéger tes variables à l'affichage

Eléphanteau du PHP | 19 Messages

17 oct. 2012, 14:47

C'est pas juste l'affichage, je me contenterai d'avoir le rang même s'il devait y avoir plusieurs instance d'un même numéro en cas d'égalité ...

J'ai fais ça et ça ne fonctionne pas :
<?php
mysql_query("SET NAMES 'utf8'");
// on recupere les infos concernant les points des joueuses
$sql = 
<<<SQL
SELECT
   id_result,
   manifestation,
   type,
   titre,
   SUM(points) as points,
   licence,
   nom,
   prenom,
   id_joueur

FROM
    resultats_opens_2012
    INNER JOIN joueur ON resultats_opens_2012.licence = joueur.id_joueur
WHERE
   resultats_opens_2012.type = "OP_FEM"

GROUP BY licence ORDER BY points DESC, nom ASC
SQL;

$req = mysql_query($sql) or die('Erreur SQL !<br />'.$req.'<br />'.mysql_error());


if(($data = mysql_fetch_array($req)) != NULL) {
	$rang = 1;
	$points = -1;

	echo '<table width="500px">'."\n";
	echo '<tr height="25" id="legend">';
	echo '<td align="center"><b>Clt</b></td>';
	echo '<td align="center"><b>Nom et Prénom</b></td>';
	echo '<td align="center"><b>Licence</b></td>';
	echo '<td align="center"><b>Points</b></td>';
	echo '</tr>'."\n";

   do {
     $rang = $points != $data['points'] ? $rang++ : $rang ;
     $points = $data['points'];
		echo '<tr>';
		echo '<td align="center">'.$rang++.'</td>';
		echo '<td>&nbsp;&nbsp;'.$data['nom'].' '.ucfirst($data["prenom"]).'</td>';
		echo '<td align="center">'.$data['licence'].'</td>';
  		echo '<td align="center">&nbsp;&nbsp;'.$points.'</td>';

    } while(($data = mysql_fetch_array($req)) != NULL);

    echo '</table>'."\n";
}
else
{
	echo '<div align="center"><h2>Aucunes joueuses dans ce clasement</h2></div>';
}

mysql_free_result($req);
?>
Tous les rangs sont à zéro :?

ViPHP
AB
ViPHP | 5818 Messages

17 oct. 2012, 20:04

Que donne le contenu de ta requête ?
Montre nous quelques lignes de ce resultat :
while(($data = mysql_fetch_array($req)) != NULL) print_r($data);

Eléphanteau du PHP | 19 Messages

17 oct. 2012, 20:50

Ca m'affiche bien un tableau avec le total des points correspondant au même numéro de licence, mais ne calcul pas le rang

Code : Tout sélectionner

Clt Nom et Prénom Licence Points 1 DUBARD Stephanie 4084 10 2 BENETEAU Sabrina 5023 8 3 CERAIS Meggy 6170 8 4 ROBALT Marilyne 14964 3
Voilà le retour du print_r($data);

Code : Tout sélectionner

Array ( [0] => 66 [id_result] => 66 [1] => ROUEN 2012 [manifestation] => ROUEN 2012 [2] => OP_FEM [type] => OP_FEM [3] => Finaliste [titre] => Finaliste [4] => 10 [points] => 10 [5] => 4084 [licence] => 4084 [6] => DUBARD [nom] => DUBARD [7] => stephanie [prenom] => stephanie [8] => 4084 [id_joueur] => 4084 ) Array ( [0] => 65 [id_result] => 65 [1] => ROUEN 2012 [manifestation] => ROUEN 2012 [2] => OP_FEM [type] => OP_FEM [3] => Vainqueur [titre] => Vainqueur [4] => 8 [points] => 8 [5] => 5023 [licence] => 5023 [6] => BENETEAU [nom] => BENETEAU [7] => sabrina [prenom] => sabrina [8] => 5023 [id_joueur] => 5023 ) ...

ViPHP
AB
ViPHP | 5818 Messages

18 oct. 2012, 04:07

Oui je me suis fait avoir comme un débutant avec l'incrémentation, remplace la ligne
$rang = $points != $data['points'] ? $rang++ : $rang ;
par
$rang = $points != $data['points'] ? ++$rang : $rang ;
Et fais attention, par la suite c'est
echo '<td align="center">'.$rang.'</td>';
et pas
echo '<td align="center">'.$rang++.'</td>';

Eléphanteau du PHP | 19 Messages

18 oct. 2012, 20:21

En effet, ça fonctionne et affiche désormais ...

Code : Tout sélectionner

Clt Nom et Prénom Licence Points 1 DUBARD Stephanie 4084 10 2 BENETEAU Sabrina 5023 8 2 CERAIS Meggy 6170 8 3 ROBALT Marilyne 14964 3 ...
toutefois, pour être conforme, ce classement devrait malgré tout afficher ROBALT Maryline "4" non ?
y a t-il beaucoup de modifications à effectuer pour parvenir à ce résultat ?

ViPHP
AB
ViPHP | 5818 Messages

19 oct. 2012, 03:49

Houlà oui c'est compliqué, ça te coûteras 1 million de dollars ...
$rang = 0;
$points = -1;
$egalite = 0;
while(($data = mysql_fetch_array($req)) != NULL)
{	 
	 if($points == $data['points'])
	 {
		 $egalite++; 
	 }
	 else if ($egalite > 0)
	 {
		$rang += $egalite+1;
		$egalite = 0;
	 }
	 else
	 {
		$rang++;
	 } 
	 
 	 $points = $data['points'];
	 
      //...
      echo '<td align="center">'.$rang.'</td>';
     //...
}
me contacter par mp pour le règlement :wink:

Mais bon pour 100 000 dollars seulement, tu peux utiliser ça :
$rang = 1;
$points = 1;
$incr = 1;
while(($data = mysql_fetch_array($req)) != NULL)
{	 
	$rang = $points == $data['points'] ? $rang : $incr;
	$incr++;
	 
 	$points = $data['points'];
	 
      //...
      echo '<td align="center">'.$rang.'</td>';
     //...
}
je pourrai pas faire moins cher :)

Eléphanteau du PHP | 19 Messages

19 oct. 2012, 08:22

Ca fonctionne parfaitement, merci beaucoup =D>

Afin de m'éclairer quelque peu quelqu'un pourrait détailler cette partie :
$rang = $points == $data['points'] ? $rang : $incr;

ViPHP
AB
ViPHP | 5818 Messages

19 oct. 2012, 16:59

C'est la syntaxe des opérateurs ternaires, expliquée ici.