Précédent   Forum des professionnels en informatique > PHP > PHP & SGBD > PHP & MySQL
PHP & MySQL Forum d'entraide sur les fonctions MySQL avec PHP. Avant de poster -> FAQ MySQL, Cours MySQL et Sources MySQL. Pour les questions concernant le moteur MySQL plutôt que les fonctions PHP, merci d'utiliser le forum MySQL.
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 01/02/2011, 07h41   #1
Expert Confirmé
 
Avatar de RunCodePhp
 
Inscription : janvier 2010
Messages : 2 706
Détails du profil
Informations personnelles :
Localisation : Réunion

Informations forums :
Inscription : janvier 2010
Messages : 2 706
Points : 3 274
Points : 3 274
Par défaut Count et Group by et Order by en conflit. Un bug ou normal ?

Salut

Je vous fais part d'un phénomène qui me parais plutôt étrange sur une banale petite requête où le ORDER BY serait entre autre l'acteur principal.

La requête à l'origine : (c'est un système de ticket interne)
Code sql :
1
2
3
4
5
6
7
8
9
10
11
 
SELECT COUNT(*) AS total
FROM ticket t
JOIN ticket_history th ON t.ticket_id = th.ticket_id
JOIN ticket_status ts ON t.status_id = ts.status_id
WHERE t.users_id = 100
AND th.publier = 1
AND t.status_id = 1
GROUP BY t.ticket_id
ORDER BY t.date_created DESC
LIMIT 1
Cette requête retourne 2 pour "total", MySQL trouve donc 2 lignes.
Or, je sais qu'il y en a 3.
-> 1 ligne ticket_id pour le user_id 100 dans la table ticket
-> 3 lignes ticket_id dans la table ticket_history (3 réponses).


Je supprime dans la requête le ORDER BY (ORDER BY t.date_created DESC), et hop, cette fois MySQL trouve bien les 3 lignes.
Depuis quand un ORDER BY agirait sur le nombre de ligne à retourner ?


Personnellement je le trouve un peu fort l'café, même ici le ORDER BY n'était pas utile.


Selon vous, c'est normal ou pas ?
Une explication serait le bienvenu.
__________________
Win XP | WampServer 2.2d | Apache 2.2.21 | Php 5.3.10 | MySQL 5.5.20
Si debugger, c'est supprimer des bugs, alors programmer ne peut être que les ajouter [Edsger Dijkstra]
RunCodePhp est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/02/2011, 09h18   #2
Membre Expert
 
Homme
Inscription : janvier 2004
Messages : 1 238
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Secteur : Finance

Informations forums :
Inscription : janvier 2004
Messages : 1 238
Points : 1 421
Points : 1 421
Bonjour,

moi ce qui me perturbe c'est le LIMIT 1 a la fin.
Si tu lui dit que tu veux un seul resultat, pourquoi il t'en retourne 2 (ou 3) ?

peut etre que mysql tri la table en interne pour réaliser le group by et que ton order by "perturbe" ce tri.

Essaye un order by par la meme colonne que la colonne de group by pour voir ?
__________________
PHP :
Regle n°1 : mysql_query(...), mysql_connect(...) et mysq_select_db(...) doivent EN DEBUG etre suivies de or die(mysql_error()); (mais jamais en production)
Regle n°2 : Mieux encore : mysql_query($requete) or die("$requete<br/>".mysql_error());
Regle n°3 : echo '<pre>';var_dump($var);echo '</pre>'; affiche le contenu et le type d'une variable.
Publiez vos textes de fantasy et de science-fiction sur http://www.cercledefaeries.com/concours/
Fladnag est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/02/2011, 10h23   #3
Expert Confirmé
 
Avatar de RunCodePhp
 
Inscription : janvier 2010
Messages : 2 706
Détails du profil
Informations personnelles :
Localisation : Réunion

Informations forums :
Inscription : janvier 2010
Messages : 2 706
Points : 3 274
Points : 3 274
Citation:
moi ce qui me perturbe c'est le LIMIT 1 a la fin.
Si tu lui dit que tu veux un seul resultat, pourquoi il t'en retourne 2 (ou 3) ?
Je ne souhaite pas que ça retourne les lignes, je veux juste connaitre le nombre de lignes de ticket_history, le nombre de réponses en faite.
D'où le COUNT(*), et d'où le LIMIT 1.

Mais effectivement, j'avais déjà fait cet essai de supprimer le LIMIT 1, ça n'a rien changé au résultat du total, du COUNT(*).

Citation:
Envoyé par Fladnag
Essaye un order by par la meme colonne que la colonne de group by pour voir ?
C'est exactement ça qui perturbe la requête.
En faite, faut pas que ça soit la même colonne que le Group by, du moins apparemment.

Si je met un tri sur la table ticket_history, ça compte bien 3 (c'est bon).
Mais dès que c'est un champ de la table ticket, ça compte 2.


C'est terrible ça.
Alors là, c'est la 1ère fois que je remarque ça.

Mais franchement, c'est normal ou pas ?
Bug ou pas bug ?
__________________
Win XP | WampServer 2.2d | Apache 2.2.21 | Php 5.3.10 | MySQL 5.5.20
Si debugger, c'est supprimer des bugs, alors programmer ne peut être que les ajouter [Edsger Dijkstra]
RunCodePhp est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/02/2011, 11h13   #4
Membre Expert
 
Homme
Inscription : janvier 2004
Messages : 1 238
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Secteur : Finance

Informations forums :
Inscription : janvier 2004
Messages : 1 238
Points : 1 421
Points : 1 421
ok pour le limit, en effet ^^ mais il ne sert a rien lui non plus je pense.

normal ? A priori je dirais non
bug ? a priori je dirais oui

Mais bon, les parseurs de SGBD sont super compliqués donc l'explication est peut etre a trouver dans le cas d'une requete super compliquée pour laquelle on a besoin de ce truc.

Essaye de faire un POC (Proof Of Concept) avec des tables, des champs et des données simples et remonte le a Mysql ;o)

Sinon il n'y a pas de champs NULL dans tes tables ?
__________________
PHP :
Regle n°1 : mysql_query(...), mysql_connect(...) et mysq_select_db(...) doivent EN DEBUG etre suivies de or die(mysql_error()); (mais jamais en production)
Regle n°2 : Mieux encore : mysql_query($requete) or die("$requete<br/>".mysql_error());
Regle n°3 : echo '<pre>';var_dump($var);echo '</pre>'; affiche le contenu et le type d'une variable.
Publiez vos textes de fantasy et de science-fiction sur http://www.cercledefaeries.com/concours/
Fladnag est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/02/2011, 08h25   #5
Expert Confirmé
 
Avatar de RunCodePhp
 
Inscription : janvier 2010
Messages : 2 706
Détails du profil
Informations personnelles :
Localisation : Réunion

Informations forums :
Inscription : janvier 2010
Messages : 2 706
Points : 3 274
Points : 3 274
Citation:
Sinon il n'y a pas de champs NULL dans tes tables ?
Il se trouve que non, tout est obligatoire, de plus que du classique coté type de données, et visuellement ça à l'air correcte.

Mais ce qui devient de plus en plus étrange, voir même plus inquiétant, c'est que je ne parviens pas à reproduire l'erreur.
Vite fait comme ça, j'ai créer une autre Bdd, tables ... et fait quelques essais des plus basiques avec les fonctions mysql_*.
Et là, avec ou sans ORDER BY, ou de LIMIT, tout est cohérent.

Vu que dans le projet en question j'utilise PDO, abstraction et tunti quanti ... qui commence à devenir un peu usine à gaz, peut être que ...


Donc je veux bien faire un PROC (jamais fais ça d'ailleurs).
Mais je me dis qu'avant d'ameuter tout l'quartier, j'aimerais bien reproduire cette erreur dans un autre contexte (en gros).

Une affaire à suivre, mais il doit avoir une explication, en espérant que c'est pas l'arbre qui cache la foret.
__________________
Win XP | WampServer 2.2d | Apache 2.2.21 | Php 5.3.10 | MySQL 5.5.20
Si debugger, c'est supprimer des bugs, alors programmer ne peut être que les ajouter [Edsger Dijkstra]
RunCodePhp est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/02/2011, 09h11   #6
Membre Expert
 
Homme
Inscription : janvier 2004
Messages : 1 238
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Secteur : Finance

Informations forums :
Inscription : janvier 2004
Messages : 1 238
Points : 1 421
Points : 1 421
Si tu n'arrives pas a reproduire le problème en repartant de zero, il faut faire l'inverse : partir du problème et simplifier tout au maximum petit a petit, en vérifiant a chaque suppression que le problème est toujours là.

Commence a faire une copie de ta base et de ton code pour ne pas casser tout ce que tu as fait, puis :
* Fait une page avec uniquement la requete qui pose probleme
* Supprime toutes les tables, champs et autres qui ne sont pas dans la requete
* Supprime tout ce qui est inutile dans le code PHP en gardant la meme architecture (POO)
* Supprime la couche d'abstraction PDO (c'est peut etre un bug de la couche aussi, va savoir ^^)
* etc...

Evidemment, ca prend du temps et ce n'est peut être pas ta priorité, mais si tu veux fouiller pour comprendre pourquoi, y a que ca a faire je crois ^^
__________________
PHP :
Regle n°1 : mysql_query(...), mysql_connect(...) et mysq_select_db(...) doivent EN DEBUG etre suivies de or die(mysql_error()); (mais jamais en production)
Regle n°2 : Mieux encore : mysql_query($requete) or die("$requete<br/>".mysql_error());
Regle n°3 : echo '<pre>';var_dump($var);echo '</pre>'; affiche le contenu et le type d'une variable.
Publiez vos textes de fantasy et de science-fiction sur http://www.cercledefaeries.com/concours/
Fladnag est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/02/2011, 09h32   #7
Expert Confirmé
 
Avatar de RunCodePhp
 
Inscription : janvier 2010
Messages : 2 706
Détails du profil
Informations personnelles :
Localisation : Réunion

Informations forums :
Inscription : janvier 2010
Messages : 2 706
Points : 3 274
Points : 3 274
Effectivement, c'est tout ça qui va falloir que je fasse pour avoir un minimum d'info avant de fusiller MySQL
(je déconne).

N'empêche que j'étais à des années lumières de tout ça, en postant ici j'étais quasi convaincu que c'était le SQL qui n'allait pas.

En tout cas faut bien voir que c'est quasi une pure coïncidence que je tombe dessus.

Normalement je ne devais pas mettre ce ORDER BY, c'est ma manie de faire du copier/coller de requêtes déjà existantes, j'ai pas du faire gaffe à l'époque.
Donc quelque part c'est un mal pour un bien.

Je vais quand même tenter de "jouer" des 2 cotés :
D'un coté tenter de reproduire cette erreur dans un contexte le plus neutre possible.
De l'autre (le site) tenter de voir quel serait le truc le plus perturbateur.

Si c'est ma classe PDO ... c'est la mer**


Et oui, je sens que ça va me prendre du temps cette histoire.
Mais comme on dit ici : "Il faut que je trouve le boute". (-> l'erreur)
__________________
Win XP | WampServer 2.2d | Apache 2.2.21 | Php 5.3.10 | MySQL 5.5.20
Si debugger, c'est supprimer des bugs, alors programmer ne peut être que les ajouter [Edsger Dijkstra]
RunCodePhp est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/02/2011, 09h51   #8
Expert Confirmé
 
Avatar de RunCodePhp
 
Inscription : janvier 2010
Messages : 2 706
Détails du profil
Informations personnelles :
Localisation : Réunion

Informations forums :
Inscription : janvier 2010
Messages : 2 706
Points : 3 274
Points : 3 274
Bon, j'ai refais d'autres essai, et hier, le café n'était peut être pas assez fort.

J'ai recréé une Bdd, autres tables (même nom, même structure, même données), et là j'ai pu reproduire la même erreur.
J'ai aussi réduit la requête au stricte minimum :
Code sql :
1
2
3
4
5
6
7
 
SELECT COUNT(*) AS total
    FROM ticket t
    JOIN ticket_status_history tsh ON t.ticket_id = tsh.ticket_id
    WHERE t.ticket_customers_id = 104
    GROUP BY t.ticket_id
    ORDER BY t.ref_ticket DESC

En faisant des essais bruts de décoffrage (en local toujours) avec 4 requêtes :
-> requêtes avec mysql_* sur les nouvelles tables (autre site/répertoire)
-> requêtes avec mysql_* sur les tables de mon projet
-> requête avec PDO sur les nouvelles tables (autre site/répertoire)
-> requête avec PDO sur les tables de mon projet

Les 4 donnent les même erreur si je laisse le ORDER BY
Les 4 donnent les bons résultats en supprimant le ORDER BY ou en indiquant un autre champ (ticket_status_history) que la table "ticket" (où cette dernière n'est pas logique).

En appliquant ces requêtes dans PhpMyAdmin, même constat.


Mais aussi, j'ai créé les mêmes tables avec SQLiteManager (donc une Bdd SQLite), et là, quelque soit la requête, les résultats sont correctes, donc même avec un ORDER BY illogique.

Une fois exécuté cette requête, si je clique dans "modifier" (le SQL), ça vire automatiquement le ORDER BY quelque peu foireux.
Donc quelque part l'API détecte bien un problème, et même le corrige.
SQLite serait il plus intelligent que MySQL ?


Rien qu'avec, j'en conclus quand même que le code de mon projet ne serait pas en cause, et même la Bdd.
Ouff ...


J'ai tendance à dire que c'est MySQL qui déconne un peu, que cette erreur serait un peu déboussolé.
Mais alors là, à quel niveau ???
Là ça me dépasse.


Personnellement, j'ai pas trop envie de m'enquiquiner plus longtemps avec ça, car de toute manière ça part d'une requête qui est foireuse.
Un ORDER BY s'appliquant sur une mauvaise table au minimum si on enlève le COUNT(*).
Ou si on laisse le COUNT(*), le ORDER BY ne sert strictement à rien.
__________________
Win XP | WampServer 2.2d | Apache 2.2.21 | Php 5.3.10 | MySQL 5.5.20
Si debugger, c'est supprimer des bugs, alors programmer ne peut être que les ajouter [Edsger Dijkstra]
RunCodePhp est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/02/2011, 10h50   #9
Membre Expert
 
Homme
Inscription : janvier 2004
Messages : 1 238
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Secteur : Finance

Informations forums :
Inscription : janvier 2004
Messages : 1 238
Points : 1 421
Points : 1 421
déjà tu as pu cerner un peu plus le problème et innocenter ton API ;o)
__________________
PHP :
Regle n°1 : mysql_query(...), mysql_connect(...) et mysq_select_db(...) doivent EN DEBUG etre suivies de or die(mysql_error()); (mais jamais en production)
Regle n°2 : Mieux encore : mysql_query($requete) or die("$requete<br/>".mysql_error());
Regle n°3 : echo '<pre>';var_dump($var);echo '</pre>'; affiche le contenu et le type d'une variable.
Publiez vos textes de fantasy et de science-fiction sur http://www.cercledefaeries.com/concours/
Fladnag est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/02/2011, 10h20   #10
Membre régulier
 
Homme Nicolas
Étudiant
Inscription : mai 2010
Messages : 308
Détails du profil
Informations personnelles :
Nom : Homme Nicolas
Localisation : France

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : mai 2010
Messages : 308
Points : 74
Points : 74
T'as des doublons dans tes réponses à sortir? Si oui, il faut utiliser DISTINCT (bon je pense que tu le savais déjà, mais juste au cas ou )
feldi est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/02/2011, 11h02   #11
Membre Expert
 
Homme
Inscription : janvier 2004
Messages : 1 238
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Secteur : Finance

Informations forums :
Inscription : janvier 2004
Messages : 1 238
Points : 1 421
Points : 1 421
non, c'est son count(*) qui renvoie 2 au lieu de 3 elements

mais on pourrait essayer count(distinct table.cle) ^^
__________________
PHP :
Regle n°1 : mysql_query(...), mysql_connect(...) et mysq_select_db(...) doivent EN DEBUG etre suivies de or die(mysql_error()); (mais jamais en production)
Regle n°2 : Mieux encore : mysql_query($requete) or die("$requete<br/>".mysql_error());
Regle n°3 : echo '<pre>';var_dump($var);echo '</pre>'; affiche le contenu et le type d'une variable.
Publiez vos textes de fantasy et de science-fiction sur http://www.cercledefaeries.com/concours/
Fladnag est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/02/2011, 12h46   #12
Expert Confirmé
 
Avatar de RunCodePhp
 
Inscription : janvier 2010
Messages : 2 706
Détails du profil
Informations personnelles :
Localisation : Réunion

Informations forums :
Inscription : janvier 2010
Messages : 2 706
Points : 3 274
Points : 3 274
Nom mais, il n'y pas vraiment à se torturer l'esprit à vouloir trouver une solution, la question n'est pas là.

La solution est toute trouvée et ça depuis le début : Dans mon cas il n'y avais absolument pas à mettre un tri (un ORDER BY).
Faire un tri sur un champ qui lui même n'est pas renvoyé, c'était absurde.
De plus, c'était un champ dans la table où il y avait qu'1 seule et unique ligne, ce qui était doublement absurde.

On peu dire que j'avais commis une erreur de syntaxe, ou du moins une instruction SQL illogique.


En faite, le truc c'était de faire un petit retour sur un comportement de MySQL qui m'a semblé un peu troublant, voir même un peu fort (l'café).


En faite, j'aurais plus vu 2 cas suivant cette requête :
- Soit MySQL juge que cette erreur illogique est anodine, et donc parviendra à retourner un résultat toujours correcte, cohérent.

- Soit MySQL juge que cette erreur est suffisamment grave (le résultat risque d'être incohérent), et bien dans ce cas retourne une erreur.


Et bien non, c'est ni l'un ni l'autre, mais à mon sens fait pire, MySQL retourne un résultat incohérent, et ça tout en silence, sans le moindre avertissement.

Donc la question : Est ce normal qu'une Base De Donnée telle que MySQL ait un comportement comme ça fasse à ce genre d'erreur ?
Il y a erreur tout de même.
Pour ma part, c'est pas normal, et j'aurais préféré 100 fois une belle erreur.

D'ailleurs, un essai a démontré que SQLite était plus robuste, retournait le bon résultat fasse à cette même erreur.


Tant qu'il s'agit d'une application sans aucun enjeu ça va.
Mais imaginez un instant que l'on "brasse" de l'argent, et bien 2 n'est pas équivalent de 3, et ça peu représenter un sacré gros paquet selon la quantité "brassée" et le temps avant de trouver l'erreur.
Pas cool MySQL
Quoi que, ça dépend à qui profite le crime



M'enfin, il n'y a pas mort d'homme non plus.
__________________
Win XP | WampServer 2.2d | Apache 2.2.21 | Php 5.3.10 | MySQL 5.5.20
Si debugger, c'est supprimer des bugs, alors programmer ne peut être que les ajouter [Edsger Dijkstra]
RunCodePhp est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 06h59.


 
 
 
 
Partenaires

Hébergement Web