2 requetes en une : UNION et COUNT

Mammouth du PHP | 531 Messages

30 sept. 2008, 00:00

Bonsoir,

Voilà après avoir retourner dans tous les sens le peu de doc que j'ai pu trouver à propos d'UNION, essayé des syntaxes différentes je vient chercher vos éclaircissements.
Je cherche tout simplement à faire un count sur 2 tables dans une seule requête mais ça n'a pas l'air aussi simple que ça en fait
 SELECT COUNT( id_post ) AS nbPost
FROM post
WHERE id_membre =1
UNION SELECT COUNT( id_topic ) AS nbTopic
FROM topic
WHERE id_membre =1 
Le résultat me retourne 2 valeurs complètement farfelues pour nbPost ( pourquoi 2 déjà c'est une bonne question) et rien du tout pour nbTopic.

Dans mon code php par contre j'ai une erreur : Notice: Undefined index: nbTopic in... etc

:?

Code : Tout sélectionner

CREATE TABLE `post` ( `id_post` int(11) NOT NULL auto_increment, `id_topic` int(11) NOT NULL, `id_membre` int(11) NOT NULL, `date` datetime NOT NULL, `message` text NOT NULL, PRIMARY KEY (`id_post`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=51 ; CREATE TABLE `topic` ( `id_topic` int(11) NOT NULL auto_increment, `id_membre` int(11) NOT NULL, `nom` varchar(250) NOT NULL, `date` datetime NOT NULL, `postit` tinyint(1) NOT NULL, `test` tinyint(1) NOT NULL, PRIMARY KEY (`id_topic`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=27 ;

Eléphant du PHP | 254 Messages

30 sept. 2008, 01:18

Salut en fait il me semble que les SELECT des requêtes qui composent ton UNION doivent contenir les mêmes sorties, donc dans ton cas il faudrait ruser ... Je rajoute en plus des parenthèses et des alias pour etre sur

Code : Tout sélectionner

(SELECT COUNT( p.id_post ) AS nbPost, 0 AS nbTopic FROM post p WHERE p.id_membre =1) UNION (SELECT 0 AS nbPost, COUNT( t.id_topic ) AS nbTopic FROM topic t WHERE t.id_membre =1);
Ça te donnera un résultat du genre

Code : Tout sélectionner

nbPost nbTopic 2 0 0 86

Bon ceci dit dans ton cas c'est un peu tricky de faire appel a un UNION alors que tes ensembles ne s'entrecoupent pas, il te suffit de faire un JOIN sur ton id_member

Code : Tout sélectionner

SELECT COUNT( p.id_post ) AS nbPost, COUNT( t.id_topic ) AS nbTopic FROM post p, topic t WHERE p.id_membre = t.id_membre AND t.id_membre =1
Ceci évidement si tu cherche bine a compter a partir du même user

Mammouth du PHP | 531 Messages

30 sept. 2008, 10:03

Salut
Merci de ta réponse
Par contre absolument rien compris à la requête avec union qui me sort effectivement 2 valeurs pour chaque colonnes mais il n'en faudrait qu'une. 2 en tout.

Pour la deuxième requête effectivement ce serrait plus logique mais le résultat est assez byzar :

125O topics, 1250 posts
ALors qu'en ai à peine 100 dans chaque tables

Eléphant du PHP | 254 Messages

30 sept. 2008, 12:09

Oui euh milles excuses, la deuxième requête est complètement fausse

La première est pas mal, normalement le résultat est juste, bien que présenté en deux ligne, ça reste facilement utilisable en php, j'vais voir si je trouve pas une amélioration tout de même

Eléphant du PHP | 254 Messages

30 sept. 2008, 13:17

Tiens essaye donc celle la sur ta base :

Code : Tout sélectionner

SELECT COUNT(DISTINCT(t.id_topic)) AS nbTopic , COUNT(p.id_post) AS nbPost FROM post p, topic t WHERE p.id_membre = t.id_membre AND t.id_topic = p.id_topic AND t.id_membre=1

Mammouth du PHP | 531 Messages

30 sept. 2008, 14:19

C'est exactement ça, en tous cas ça marche mais par contre je suis largué :lol:

Je comprend pas du tout pourquoi on fait un distinct sur t.id_topic :?

Eléphant du PHP | 254 Messages

30 sept. 2008, 16:46

En fait j'ai procédé par étape et sur un petit échantillon, ça aide a la réflexion, j'ai commencé par

Code : Tout sélectionner

SELECT * FROM post p, topic t WHERE p.id_membre = t.id_membre AND t.id_membre=1
Dans mon exemple (2 topics avec 3 posts) ça me donnait 6 lignes de résultats, j'ai donc rajouté

Code : Tout sélectionner

AND t.id_topic = p.id_topic
, car les autres lignes n'avaient aucun sens

Il me restait donc trois lignes, correspondant au tableau des posts, avec leurs topics associé

Code : Tout sélectionner

topic | post 1 1 1 2 2 3
Une fois ce résultat obtenu tu vois aisément que tu peux compter directement les posts, mais qu'il te faut compter les topics uniques, d'où le DISTINCT

Mammouth du PHP | 531 Messages

02 oct. 2008, 00:36

Merci c'est bien mieux avec des explications =)

Mammouth du PHP | 531 Messages

03 oct. 2008, 20:38

Je réouvre le topic.
En fait il y à un petit problème...

La requête ne marche que si l'on à créé un topic. Mais si l'on à seulement répondu à un post, l'id membre n'apparaissant donc pas dans la table topic, le compteur reste à zéro car :
WHERE p.id_membre = t.id_membre
J'ai donc pensé à ça mais ça ne change rien à priori :
SELECT COUNT(DISTINCT(t.id_topic)) AS nbTopic , COUNT(p.id_post) AS nbPost 
	FROM post p, topic t 
	WHERE p.id_membre = $idMembre 
	AND t.id_topic = p.id_topic 
	AND t.id_membre= $idMembre

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

04 oct. 2008, 01:05

Tu dois faire dans ce cas une jointure externe qui te permettra d'inclure les posts même si aucun topic n'est joint.

Code : Tout sélectionner

SELECT COUNT(DISTINCT(t.id_topic)) AS nbTopic , COUNT(p.id_post) AS nbPost FROM post p LEFT JOIN topic t ON (p.id_membre = t.id_membre AND t.id_topic = p.id_topic) WHERE t.id_membre=$idMembre
LEFT JOIN = Jointure externe à gauche. La table de gauche étant ici "post". La requête retournera alors tous les enregistrements de "post" (qui bien sûr correspondent à $idMembre) et seulement ceux de table "topic" qui respectent le critère de jointure.
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène