Consultez la FAQ sur le ZF avant de poster une question
Vous n'êtes pas identifié.
Bonjour,
Voila, j'ai plusieurs table et je souhaiterai en sortire une statistique.
table1 = user
table2 = post
table3 = comment
table4 = abuse
table5 = abuse_comment
Je souhaiterai définir quel "user" à le plus d'entrées lui correspondant, dans la table "abuse" et d'en ressortir les 10 premiers.
La structure est une simple hierarchie, soit:
La table "abuse_comment" possède la colonne "comment_id" de l'ID du commentaire qui lui correspond
La table "abuse" possède la colonne "post_id" de l'ID du poste qui lui correspond
La table "comment" possède la colonne "post_id" de l'ID du poste qui lui correspond
La table "post" possède la colonne "user_id" de l'ID de l'utilisateur qui lui correspond
Graphiquement cela pourrait donner cela:
user
|- post
|-- abuse
|-- comment
|--- abuse_comment
Ma technique est la suivante:
$select = $this->db->select(); $select->from(array('us' => 'user')); $select->join(array('po' => 'post'), 'po.user_id = us.user_id', array('total_post' => 'COUNT(*)')); $select->group('us.user_id'); $select->limit(10); $select->order(array('total_post DESC')); return $this->db->fetchAll($select);
Jusqu'à la tout roule, la valeur total_post, est juste ! Il me sort un tableau comme celui-ci:
Array ( [0] => Array ( [user_id] => 1 [user_firstname] => *** [user_secondname] => *** [user_username] => *** [user_email] => *** [user_password] => *** [user_country] => 38 [user_picture] => profile_1.jpg [user_key_confirm] => [user_create_date] => 2009-05-04 10:47:27 [user_block] => 0 [total_post] => 3 ) [1] => Array ( [user_id] => 2 [user_firstname] => *** [user_secondname] => *** [user_username] => *** [user_email] => *** [user_password] => *** [user_country] => 38 [user_picture] => [user_key_confirm] => [user_create_date] => 2009-05-04 23:59:58 [user_block] => 0 [total_post] => 2 ) )
Mais alors dès lors que j'ajout une jointure et un COUNT() ça foire.
Exemple avec cette requête:
$select = $this->db->select(); $select->from(array('us' => 'user')); $select->join(array('po' => 'post'), 'po.user_id = us.user_id', array('total_post' => 'COUNT(*)')); $select->join(array('ab' => 'abuse'), 'ab.post_id = po.post_id', array('total_post_abuse' => 'COUNT(*)')); $select->group('us.user_id'); $select->limit(10); $select->order(array('total_post DESC', 'total_post_abuse DESC')); return $this->db->fetchAll($select);
elle me changera les valeurs de la variable "total_post", par celle de "total_post_abuse" (tableau ci-dessous), c'est bien dommage étant donné que la valeur "total_post_abuse" est juste, mais que "total_post" est maintenant fausse. Voyez plutôt:
Array ( [0] => Array ( [user_id] => 1 [user_firstname] => *** [user_secondname] => *** [user_username] => *** [user_email] => *** [user_password] => *** [user_country] => 38 [user_picture] => profile_1.jpg [user_key_confirm] => [user_create_date] => 2009-05-04 10:47:27 [user_block] => 0 [total_post] => 8 [total_post_abuse] => 8 ) [1] => Array ( [user_id] => 2 [user_firstname] => *** [user_secondname] => *** [user_username] => *** [user_email] => *** [user_password] => *** [user_country] => 38 [user_picture] => [user_key_confirm] => [user_create_date] => 2009-05-04 23:59:58 [user_block] => 0 [total_post] => 6 [total_post_abuse] => 6 ) )
Pourriez-vous me dire pourquoi la première valeur change?
Merci d'avance!
Hors ligne
tu fais un echo de $select->__toString();
ça va t'afficher la requête que tu veux mais ça me parait normal
tu ne peux avoir 2 count(*) dans les colonnes
le count te compte le nombre de lignes de la requête pas des élément de la table de ta jointure
tu fais deux objet select un sur chaque table post et abuse avec chacune un count
puis tu fait une troisième requête et tu fais une jointure sur les deux précédente
A+JYT
Hors ligne
Hello,
C'est parce que tu fais 2 fois COUNT(*) donc tu reçois 2 fois la même valeur. Je n'ai pas regardé en détails mais je n'ai pas l'impression que tu puisses faire ceci sans une sous-requête.
A+
Hors ligne
sekaijin > Merci je crois avoir à peut prêt compris Je regarde et je poste si ça fonctionne
mikaelkael > Merci. J'ai essayé de changer la valeur * par "po.user_id" pour le premier et "ab.post_id" pour le deuxième, mais ça ne change rien !
Je vous tiens au jus !
Hors ligne
Non, en fait sekaijin, j'ai rien suivis T'aurai pas un exemple, même minime, afin que j'y voie plus claire.
Merci
Hors ligne
je te donne le truc à la volé sans tester ni vérifier juste pour l'idée
$selectPost = $this->db->select(); $selectPost->from('post', array('user_id', 'total_post' => new Zend_Db_Expr('COUNT(1)'))); $selectPost->groupBy('user_id') $selectAbuse = $this->db->select(); $selectAbuse->from('abuse', array('post_id', 'total_post_abuse' => new Zend_Db_Expr('COUNT(1)'))); $selectAbuse->groupBy('post_id') $select = $this->db->select(); $select->from(array('us' => 'user')); $select->join(array('po' => $selectPost), 'po.user_id = us.user_id', 'po.total_post'); $select->join(array('ab' => $selectAbuse), 'ab.post_id = po.post_id', 'ab.total_post_abuse'); $select->group('us.user_id'); $select->limit(10); $select->order(array('po.total_post DESC')); return $this->db->fetchAll($select);
Je ne garantis pas la syntaxe exacte mais c'est le principe ça n'a rien à voir avec ZF cest ainsi qu'il faut faire en SQL
SELECT 'us'.*, 'po'.'total_post', 'ab'.'total_post_abuse' FROM 'user' AS 'us' INNER JOIN ( SELECT 'user_id', COUNT(1) AS 'total_post' FROM 'post' GROUP BY 'user_id' ) AS 'po' ON ('po'.'user_id' = 'us'.'user_id') INNER JOIN ( SELECT 'post_id', COUNT(1) AS 'total_post_abuse' FROM 'abuse' GROUP BY 'post_id' ) AS 'ab' ON ('ab'.'post_id' = 'po'.'post_id') GROUP BY 'us'.'user_id' ORDER BY 'po'.'post_total' DESC LIMIT 10
A+JYT
Hors ligne
Bon après 1jour de perdu sur ce truc à la con, ça commence à bien faire
En fait j'ai essayé de débuger le code que tu m'as proposé, ci-dessus, mais rien à faire, la réponse est toujours fausse.
En premier si je fais pas une jointure de gauche à droite (joinLeft) alors il ne me sort aucun résultat. Après même si j'utilise une jointure Left, (n'ayant pas obligatoirement une entrée pour chaque élément parent) j'obtiens un résultat correct pour le nombre de poste mais pas pour le nombre d'abus !
Voici le code qui fonctionne (enfin, presque :
$selectPost = $this->db->select(); $selectPost->from('post', array('user_id', 'post_id', 'total_post' => new Zend_Db_Expr('COUNT(1)'))); $selectPost->group('user_id'); $selectAbuse = $this->db->select(); $selectAbuse->from('abuse', array('post_id', 'total_post_abuse' => new Zend_Db_Expr('COUNT(1)'))); $selectAbuse->group('post_id'); $select = $this->db->select(); $select->from(array('us' => 'user')); $select->joinLeft(array('po' => $selectPost), 'po.user_id = us.user_id', 'po.total_post'); $select->joinLeft(array('ab' => $selectAbuse), 'ab.post_id = po.post_id', 'ab.total_post_abuse'); $select->group('us.user_id'); $select->limit(10); return $this->db->fetchAll($select);
le résultat est:
Array ( [0] => Array ( [user_id] => 1 [user_firstname] => *** [user_secondname] => *** [user_username] => *** [user_email] => *** [user_password] => *** [user_country] => 38 [user_picture] => profile_1.jpg [user_key_confirm] => [user_create_date] => 2009-05-04 10:47:27 [user_block] => 0 [total_post] => 3 [total_post_abuse] => ) [1] => Array ( [user_id] => 2 [user_firstname] => *** [user_secondname] => *** [user_username] => *** [user_email] => *** [user_password] => *** [user_country] => 38 [user_picture] => [user_key_confirm] => [user_create_date] => 2009-05-04 23:59:58 [user_block] => 0 [total_post] => 2 [total_post_abuse] => 1 ) )
Problème: la valeur "total_post_abuse" devrait être pour le deuxième tableau de "2" et non pas "1".
Vous ne sauriez pas pourquoi ?
Hors ligne
ce n'est pas un problème avec ZF
ne sachant pas ce que tu cherche on ne peux pas t'aider bien plus
écris ta requête en SQL teste la et quand tu as ton résultat tu la mets à la sauce ZF
je ne comprends pas pourquoi ce serait dans un autre tableau quand tu fais une jointure tu n'as qu'un tableau de valeur
A+JYT
Hors ligne
Autant pour moi, quand je dis tableau, je parle de la deuxième position du tableau = array[1]['total_post_abuse'].
Écrire la requête ne me serait pas très utile, étant donné que pour moi, la requête est on ne peut plus logique. Alors écrire la requête en SQL, ne ferait que de traduire ce que j'écris déjà via l'ORM.
En fait, à ce que j'ai pu comprendre dans mon debugage, c'est que la requête ne calcule pas l'ensemble des abus pour tous les postes correspondant au membre, mais qu'il calcule l'ensemble des abus pour le premier poste correspondant au membre.
Par conséquent le résultat "1" correspond au nombre d'abus du premier poste du membre, hors moi je souhaite comptabiliser le nombre d'abus sur la totalité des postes et cela par membre.
Par conséquent la boucle va devoir chercher l'ensemble des abus pour chaque postes et pour chaque membre.
Finalité: j'aimerai que ma requête fasse une boucle sur chaque poste et qu'il comptabilise combien d'abus lui correspondant.
Est-ce que je suis plus claire ? Désolé c'est difficile à expliquer comme ça !
En tout cas merci beaucoup pour votre aide.
Hors ligne
Badoux a écrit:
Écrire la requête ne me serait pas très utile, étant donné que pour moi, la requête est on ne peut plus logique. Alors écrire la requête en SQL, ne ferait que de traduire ce que j'écris déjà via l'ORM.
Je pense que ce que voulais dire sekaijin est que tu "gagnerais" du temps d'écrire directement ta requête en SQL et de l'exécuter dans phpMyAdmin.
C'est en tout cas ce que je fais pour les requêtes complexes que je ne suis pas sûr de retranscrire correctement en ZF.
Hors ligne
alors si tu veux deux ligne il te faut faire l'union de deux requête
mais attention dans une union toute les colonnes des deux requête on le même libelle
SELECT COUNT(1) AS 'total' FROM 'post' UNION SELECT COUNT(1) AS 'total' FROM 'abuse'
tu ne peux pas avoir total_post et total_post_abuse à moins de créer des colonnes vides
SELECT COUNT(1) AS 'total_post', NULL AS 'total_post_abuse' FROM 'post' UNION SELECT NULL AS 'total_post', COUNT(1) AS 'total_post_abuse' FROM 'abuse'
A+JYT
Hors ligne