Moyenne sur un champs du type varchar

WRInaute passionné
Salut à tous,

Je stock dans une table MySql dans un champs du type varchar des dimensions en millimètres, sous cette forme :
Code:
8.58x5.56x3.02
8.83x5.67x3.09
8.04x5.25x3.07
Le premier chiffre correspond à la longueur, le deuxième à la largeur et le dernier à la hauteur, par exemple pour le premier enregistrement : 8.58 est la longueur, 5.56 est la largeur et 3.02 est la hauteur.

Peut-on avec une requête mysql obtenir la moyenne des longueurs, des largeurs et des hauteurs ?

Je sais qu'un SELECT AVG( moyenne ) AS moyenneLongueur FROM ma_table pourrait faire le job mais ça ne fonctionne pas sur un champs du type varchar, voyez-vous une requête mysql qui puisse faire cela ?

Merci pour vos réponses.
 
WRInaute passionné
pourquoi ne pas stocker dans des colonnes différentes? parce que avec les caractères spéciaux je vois pas comment le gérer.

Après ça se fait très bien en PHP
 
WRInaute passionné
Quelque chose du genre :

SELECT AVG(CAST(SUBSTRING(champ, 1, 4) AS DECIMAL(5,2))) AS moyenneLongueur

En supposant que les longueurs sont sur 4 caractères, sinon il faut chercher le 'x' pour ajuster.
 
WRInaute passionné
Merci pour vos réponses.

Après ça se fait très bien en PHP
Comment tu fais pour calculer une moyenne en PHP, il n'y a pas de fonction php pour cela, non ?

Quelque chose du genre :

SELECT AVG(CAST(SUBSTRING(champ, 1, 4) AS DECIMAL(5,2))) AS moyenneLongueur

En supposant que les longueurs sont sur 4 caractères, sinon il faut chercher le 'x' pour ajuster.
Malheureusement le nombre de caractères des longueurs, largeurs et hauteur peut varier. Ca peut être du style 8x5.67x3.10 ou bien 8.8x5x3, c'est très variable.
 
WRInaute impliqué
Je stock dans une table MySql dans un champs du type varchar des dimensions en millimètres

Clairement pas une bonne structuration de la base de donnée.

Les solutions données ne peuvent être que moyennement adaptée. Celle suggérée par @rick38 est une bonne base, à compléter d'un LOCATE() pour rechercher la position du x, mais ça va devenir une requête assez barbare…
 
WRInaute passionné
Clairement pas une bonne structuration de la base de donnée.

Les solutions données ne peuvent être que moyennement adaptée. Celle suggérée par @rick38 est une bonne base, à compléter d'un LOCATE() pour rechercher la position du x, mais ça va devenir une requête assez barbare…
Oui je sais que c'est pas top comme structure mais ma table a déjà 46 champs, s'il faut encore en rajouter je ne sais si c'est mieux comme solution :( d'autant plus que je ne vais pas faire appel à cette requête très souvent.

Sinon en php quelle serait la solution pour faire une moyenne des longueurs ?

Je peux récupérer toutes mes longueurs dans une boucle for du style :
Code:
for($i8=0;$i8<sizeof($headers);$i8++){
$result = get_requete("SELECT * FROM ma_table WHERE ma_requete_mysql)");
$voir = $MysqliFetchArray($result);
$longueur = explode("x",$voir['Longueur']);
// Comment calculer la moyenne de toutes les longueurs contenues dans la variable $longueur ?
}
 
WRInaute impliqué
Le nombre de colonnes en lui-même n'est pas forcément très problématique je suis plus préoccupé par la difficulté pour un SGBD de manier un varchar qu'un champ numérique. En terme de taille à proprement parler, ça peut se discuter, pour peu de chiffres significatifs 3 DOUBLE (éviter le FLOAT avec MySQL / MariaDB) va prendre plus de place qu'un VARCHAR, mais ce n'est plus vrai avec un plus grand nombre de chiffres significatifs.

On peut se demander si toutes les colonnes sont utiles, et si une jointure avec une autre table n'est pas plus pertinente. Mais dans tous les cas, je ne vois guère de justification, dans ce cas, d'utiliser une colonne "agrégeant" plusieurs valeurs, alors qu'il y a trois données très clairement identifiables et pertinentes et que trois colonnes m'apparaissent plus pertinentes d'un point de vue de la BDD.

Enfin, si le nombre de colonnes est préoccupant (et donc le volume de données), on peut faire un SELECT plus ciblé que SELECT *.

Je trouve au demeurant que la BDD gagne en lisibilité (quelle valeur est la longueur ?) et bien sûr en opérabilité (tri suivant une taille, calcul du volume, sélection de la plus grande valeur, etc.).

Quand au code PHP, j'ai du mal à comprendre ton approche. À quoi correspond $header ? pourquoi faire une requête en boucle ?

La solution plus "pragmatique" serait de sélectionner toutes les lignes en une requête unique, puis de toutes les parcourir (avec un foreach plutôt qu'un for), et enfin calculer une moyenne, comme on fait en arithmétique, tu additionne d'un côté les valeurs et à la fin, tu divises par le nombre de valeurs.
 
WRInaute passionné
Ce n'est clairement pas propre, mais si c'est une petite base qui n'a pas des dizaines de milliers d'enregistrements, des milliers de visiteurs qui font la requête en même temps, ça n'a pas d'importance côté performances. Il faut voir la prise de tête et temps de développement par rapport à l'intérêt de la chose, il doit faire ce qu'il lui semble le plus simple... Ca ne sera pas pire qu'une base de données de WordPress !...
Il faut ajouter le LOCATE au SELECT que j'ai proposé :
SELECT AVG(CAST(SUBSTRING(champ, 1, LOCATE('x', champ) - 1) AS DECIMAL(7,2))) AS moyenneLongueur
 
WRInaute passionné
Comment tu fais pour calculer une moyenne en PHP, il n'y a pas de fonction php pour cela, non ?

pour la moyenne tu boucles sur tous les éléments de la colonne de ta table (tu mets un explode pour séparer tes éléments avec le x), tu les additionnes et tu mets un compteur qui s’incrémente à chaque itération pour compter le nombre d'éléments et tu divises la somme des éléments par leur nombre.
 
WRInaute passionné
Merci pour ta réponse ABCWEB qui m'a bien aidé, j'ai pu calculer la moyenne des dimensions en php ;)

Comme c'est une requête mysql qui ne sera pas exécutée très souvent je vais laisser ma table comme cela, ça fait le job.

Problème résolu.
 
Discussions similaires
Haut