Zend FR

Consultez la FAQ sur le ZF avant de poster une question

Vous n'êtes pas identifié.

#1 15-05-2009 15:58:59

Badoux
Membre
Date d'inscription: 25-03-2008
Messages: 32

Plusieurs COUNT() dans une requête

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:

Code:

$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:

Code:

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:

Code:

$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:

Code:

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

 

#2 15-05-2009 16:18:54

sekaijin
Membre
Date d'inscription: 17-08-2007
Messages: 1137

Re: Plusieurs COUNT() dans une requête

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

 

#3 15-05-2009 16:19:16

mikaelkael
Administrateur
Lieu: Donges
Date d'inscription: 18-06-2007
Messages: 1176
Site web

Re: Plusieurs COUNT() dans une requête

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+


Less code = less bugs
Contributeur ZF - ZCE - ZFCE - Doc ZF (CHM & PDF) - Vice-trésorier AFUP 2011
Ubuntu 11.04 - ZendServer

Hors ligne

 

#4 15-05-2009 16:23:13

Badoux
Membre
Date d'inscription: 25-03-2008
Messages: 32

Re: Plusieurs COUNT() dans une requête

sekaijin > Merci je crois avoir à peut prêt compris wink 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

 

#5 15-05-2009 16:28:41

Badoux
Membre
Date d'inscription: 25-03-2008
Messages: 32

Re: Plusieurs COUNT() dans une requête

Non, en fait sekaijin, j'ai rien suivis wink T'aurai pas un exemple, même minime, afin que j'y voie plus claire.

Merci

Hors ligne

 

#6 16-05-2009 14:02:11

sekaijin
Membre
Date d'inscription: 17-08-2007
Messages: 1137

Re: Plusieurs COUNT() dans une requête

je te donne le truc à la volé sans tester ni vérifier juste pour l'idée

Code:

$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

Code:

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

 

#7 17-05-2009 19:09:32

Badoux
Membre
Date d'inscription: 25-03-2008
Messages: 32

Re: Plusieurs COUNT() dans une requête

Bon après 1jour de perdu sur ce truc à la con, ça commence à bien faire hmm

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 wink:

Code:

$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:

Code:

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

 

#8 17-05-2009 21:04:10

sekaijin
Membre
Date d'inscription: 17-08-2007
Messages: 1137

Re: Plusieurs COUNT() dans une requête

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

 

#9 17-05-2009 23:43:22

Badoux
Membre
Date d'inscription: 25-03-2008
Messages: 32

Re: Plusieurs COUNT() dans une requête

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 ! hmm

En tout cas merci beaucoup pour votre aide.

Hors ligne

 

#10 18-05-2009 09:22:47

acharrex
Membre
Lieu: Suisse
Date d'inscription: 27-04-2008
Messages: 135

Re: Plusieurs COUNT() dans une requête

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

 

#11 18-05-2009 10:51:10

sekaijin
Membre
Date d'inscription: 17-08-2007
Messages: 1137

Re: Plusieurs COUNT() dans une requête

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

Code:

   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

Code:

   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

 

Pied de page des forums

Propulsé par PunBB
© Copyright 2002–2005 Rickard Andersson
Traduction par punbb.fr

Graphisme réalisé par l'agence Rodolphe Eveilleau
Développement par Kitpages