Aller au contenu

[SQL] HAVING ne marche qu'avec la top line


qui.dominatur

Messages recommandés

Bonjour,

voici ma requête initiale :

SELECT    AVG(tyd.price) AS avg_price, COUNT(tyd.id_product) AS cnt,    tyd.id_marchand, tyd.id_product,    catalog.price AS c_price, tyd.price AS t_price,    tyd.amount AS t_am, pro_tyd.amount AS p_am,    pro_tyd.price AS p_price, catalog.img_src,     tyd.step, tyd.login AS tyd_l   FROM catalog   INNER JOIN tyd ON catalog.id_marchand = tyd.id_marchand			   AND catalog.id_product =   tyd.id_product			   AND tyd.step = "1"   INNER JOIN pro_tyd  ON tyd.id_marchand = pro_tyd.id_marchand				    AND tyd.id_product = pro_tyd.id_product   GROUP BY	 catalog.id_product, catalog.id_marchand   HAVING	 tyd.login = "user1@tyd.fr"

sur la table tyd suivante :

id  id_marchand  id_product   login	   price  amount  delay  step    time  29	  1		   1	   user3@tyd.fr   344	 1	   0	  1   1343297500120	 1		   1	   user1@tyd.fr   54	  1	   0	  1   1343297504109	 1		   1	   user10@tyd.fr  34	  1	   0	  1   1343298598

Le but de cette requête est d'avoir AVG et COUNT de toute les lignes ou id_product and id_marchand sont égales à ceux figurant sur la ligne ou j'ai login = "user1" AND step = "1". Ainsi que les autres champs dans le SELECT correspondant toujours à cette ligne.

Cette requête marche parfaitement bien si je met HAVING tyd.login = "user3" et me renvoit un résultat vide si user1 ou user10.

Si je supprime la ligne user3, la requête marche avec user1 mais toujours pas avec user10 et ainsi de suite. Donc elle ne marche que avec la première ligne.

Pourquoi ?? J'ai beau cherché, je ne vois vraiment pas.

J'espère que vous pourrez m'aider !

Lien vers le commentaire
Partager sur d’autres sites

Pourquoi utilises tu "having" ?

la clause login n'est pas "calculée" et est présente en base, utilise un "where" simplement

Pourquoi ca plante ?

Ba en fait tu fais un "group by" donc tu "unifies" tes données en X catégories dans une table temporaire.

J'ai pas regardé le détail de ton code, mais en gros certaines de tes lignes (ou toutes) vont se fusionner en une seule, et c'est la première ligne "du groupe" qui va être renvoyée.

mais sincèrement ca m'étonne déjà de voir deux clauses à un "group by" :D

Donc pas de Group by ( en tout cas pas si tu veux tester toutes les lignes ), et utilise un where au lieu du having :yes:

Lien vers le commentaire
Partager sur d’autres sites

Si j'utilise un WHERE, mes fonctions AVG et COUNT ne porteront que sur une seule ligne. Or je veux la moyenne de toutes les lignes ou id_product et id_marchand sont identique. C'est d'ailleurs pour ça que j'utilise le group_by.

Ce qui est fou c'est que cette requête marche parfaitement si je mets tyd.step = 0. J'obtiens toutes les lignes ou j'ai login = user 1 and step = 0 avec les AVG et COUNT des id_product et id_marchand correspondant à ces précédentes lignes.

Quand je mets STEP = 1. Je n'obtiens plus qu'une seule ligne.

J'ai posé le problème sur stackoverflow et il semble que la requête ne devrait pas marcher avec STEP = 0. Ils me recommandent de faire des sous-requêtes. Affaire à suivre.

Lien vers le commentaire
Partager sur d’autres sites

Le WHERE s'applique avant le GROUP BY, le HAVING après.

Ta requête n'est pas correcte et ne devrait même pas s'exécuter : on ne doit pas mettre de champ dans le SELECT sans fonction d'agrégation (sauf bien sûr s'ils sont présents dans le GROUP BY). Il me semble que dans ce cas, MySQL renvoie une valeur quelconque prise dans le groupe.

Lien vers le commentaire
Partager sur d’autres sites

En essayant comme ça:

SELECT	    AVG(T.price) AS avg_price, COUNT(T.id_product) AS cnt,	    T.id_marchand, T.id_product,	    C.price AS c_price, T.price AS t_price,	    T.amount AS t_am, P.amount AS p_am,	    P.price AS p_price, C.img_src,	    T.step, T.login AS tyd_l   FROM catalog C   INNER JOIN tyd T ON C.id_marchand = T.id_marchand							   AND C.id_product =   T.id_product							   AND tyd.step = "1"   INNER JOIN pro_tyd  P ON T.id_marchand = P.id_marchand									    AND T.id_product = P.id_product   WHERE			 tyd.login = "user1@tyd.fr"   GROUP BY	    T.id_marchand, T.id_product,	    C.price, T.price,	    T.amount, P.amount,	    P.price , C.img_src,	    T.step, T.login;

J'ai utilisé des alias de table, juste par flemme :p

Comme le dit Olipla, tu ne peux pas renvoyer des champs dans un SELECT sans les mettre dans un GROUP BY si tu as utilisé des fonctions (avg, count, etc).

Cette requête me paraît syntaxiquement correcte (vu l'heure à laquelle je poste), mais il faudrait avoir un schéma de ta base pour vérifier qu'elle fonctionne...

Lien vers le commentaire
Partager sur d’autres sites

Archivé

Ce sujet est désormais archivé et ne peut plus recevoir de nouvelles réponses.

×
×
  • Créer...