Moyenne un peu compliquée

Moyenne un peu compliquée - SQL/NoSQL - Programmation

Marsh Posté le 21-12-2006 à 15:14:50    

Bonjour,

 

Je bloque pour calculer une moyenne alors que ça ne doit pas être si compliqué (en MySQL).

 

En gros, j'ai 2 tables "cochon" et "user" :
Cochon (id_cochon, id_user, ...)
User (id_user, ...)

 

Je voudrais calculer le nombre moyen de cochons par user.

 

Je me doute qu'il faut utiliser la fonction avg, mais je ne vois pas comment :/

 

Merci d'avance :jap:


Message édité par nero27 le 21-12-2006 à 15:15:34
Reply

Marsh Posté le 21-12-2006 à 15:14:50   

Reply

Marsh Posté le 21-12-2006 à 15:41:14    

ca devait marcher :

 

SELECT COUNT(idCochon)/COUNT(DISTINCT idUser) as nb_cochon_par_user  FROM cochon

 

Message cité 1 fois
Message édité par flo850 le 21-12-2006 à 15:41:23
Reply

Marsh Posté le 21-12-2006 à 16:25:25    

select avg(cnt) from select count(*) as cnt from cochon group by id_user


Message édité par polo021 le 21-12-2006 à 16:26:34
Reply

Marsh Posté le 21-12-2006 à 17:14:11    

SELECT COUNT(*) AS nb_cochons FROM Cochon
SELECT COUNT(*) AS nb_users FROM User
Et on fait la division entre les 2 dans le script appellant
 
(2 requêtes, certes, mais super optimisées :o )

Reply

Marsh Posté le 21-12-2006 à 17:21:25    

à vue de nez, c'est la première qui est la plus rapide

Reply

Marsh Posté le 21-12-2006 à 18:36:49    

je suis fatigué où la 1ere requête va toujours remonter 1 ???

Reply

Marsh Posté le 21-12-2006 à 18:56:27    

flo850 a écrit :

ca devait marcher :  
 
SELECT COUNT(idCochon)/COUNT(DISTINCT idUser) as nb_cochon_par_user  FROM cochon


Celle-ci est nickel, merci :jap:

Reply

Marsh Posté le 21-12-2006 à 18:57:35    

anapajari a écrit :

je suis fatigué où la 1ere requête va toujours remonter 1 ???


 
non, count(distinct champ) retourne le nombre d'occurences différentes du champ.
donc on a bien count(distinct iduser) <= count(idcochon) dans la table cochon

Message cité 1 fois
Message édité par MagicBuzz le 21-12-2006 à 18:57:53
Reply

Marsh Posté le 21-12-2006 à 19:07:51    

On notera tout de même que cette requête calcule le nombre moyens de cochons parmi les users qui ont au moins un cochon. S'il y en a qui n'en ont pas, ils ne seront pas pris en compte dans le calcul.
(il était fondamental de le signaler :o )

Reply

Marsh Posté le 21-12-2006 à 20:17:21    

effectivement apres verification sur db2 (mais sans données de masse), la query de flo est + rapide que la mienne

Message cité 1 fois
Message édité par polo021 le 21-12-2006 à 20:17:44
Reply

Marsh Posté le 21-12-2006 à 20:17:21   

Reply

Marsh Posté le 21-12-2006 à 21:26:50    

anapajari a écrit :

je suis fatigué où la 1ere requête va toujours remonter 1 ???


quand même , je  ne mets pas que des conneries  [:twixy]  

mrbebert a écrit :

On notera tout de même que cette requête calcule le nombre moyens de cochons parmi les users qui ont au moins un cochon. S'il y en a qui n'en ont pas, ils ne seront pas pris en compte dans le calcul.
(il était fondamental de le signaler :o )


 c'est un point important, je suis parti de l'a priori ( pas forcement vrai ) qu'il y avait au moins un cochon par user

Reply

Marsh Posté le 21-12-2006 à 23:05:39    

En effet, le fait qu'il y ait au moins un cochon par user était ce qu'il me fallait ;)

Reply

Marsh Posté le 22-12-2006 à 10:12:23    

MagicBuzz a écrit :

non, count(distinct champ) retourne le nombre d'occurences différentes du champ.
donc on a bien count(distinct iduser) <= count(idcochon) dans la table cochon


ça je suis d'accord que tu as bien une infériorité, mais l'opération sur deux fonctions d'aggrégation ça m'apparait toujours moyen ... Mais bon j'ai testé sous MySQL ça marche.
Par contre

polo021 a écrit :

effectivement apres verification sur db2 (mais sans données de masse), la query de flo est + rapide que la mienne


Tu peux me montrer les query et les résultats que tu as fait? Nan parce que moi sous db2 ça me donne:

[db2inst1@prod db2inst1]$ db2 "select count(fin_id), count(distinct fin_iddos) from finan"
 
1           2
----------- -----------
    5307596     2894135
 
  1 record(s) selected.
 
[db2inst1@prod db2inst1]$ db2 "select count(fin_id)/ count(distinct fin_iddos) from finan"
 
1
-----------
          1
 
  1 record(s) selected.


Normal que ça soit plus rapide :o :o  ( c'est un db2 V8.1FP8)

Reply

Marsh Posté le 22-12-2006 à 11:11:32    

ça c'est parceque DB2 est crétin et que le COUNT() retourne un INT au lieu d'un NUMERIC : là tu fais une division entre deux entiers. donc le count retourne un entier. 2 > 5 307 596 / 2 894 135 > 1 donc en entier ça fait 1.
avec un NUMERIC (donc nombre décimal) ça doit marcher.
 
il suffit donc caster les valeur de retour en numeric ou float au moment de la division pour retrouver le bon résultat.

Message cité 1 fois
Message édité par MagicBuzz le 22-12-2006 à 11:14:07
Reply

Marsh Posté le 22-12-2006 à 11:13:30    

Avec Oracle :
 


COUNT(*) COUNT(DISTINCT NUMEVE) COUNT(*)/COUNT(DISTINCT NUMEVE)
753435   230273                 3.27192072018865


Message édité par MagicBuzz le 22-12-2006 à 11:15:13
Reply

Marsh Posté le 22-12-2006 à 11:16:25    

mrbebert a écrit :

On notera tout de même que cette requête calcule le nombre moyens de cochons parmi les users qui ont au moins un cochon.


en effet. il reste à savoir si les utilisateurs sans kochons sont à prendre en considération ou non.

Reply

Marsh Posté le 22-12-2006 à 11:17:20    

MagicBuzz a écrit :

ça c'est parceque DB2 est crétin et que le COUNT() retourne un INT au lieu d'un NUMERIC : là tu fais une division entre deux entiers. donc le count retourne un entier. 2 > 5 307 596 / 2 894 135 > 1 donc en entier ça fait 1.
avec un NUMERIC (donc nombre décimal) ça doit marcher.
 
il suffit donc caster les valeur de retour en numeric ou float au moment de la division pour retrouver le bon résultat.


 :jap: yes master! Totally true!

Reply

Marsh Posté le 22-12-2006 à 11:51:46    

anapajari a écrit :

ça je suis d'accord que tu as bien une infériorité, mais l'opération sur deux fonctions d'aggrégation ça m'apparait toujours moyen ... Mais bon j'ai testé sous MySQL ça marche.
Par contre
 
Tu peux me montrer les query et les résultats que tu as fait? Nan parce que moi sous db2 ça me donne:

[db2inst1@prod db2inst1]$ db2 "select count(fin_id), count(distinct fin_iddos) from finan"
 
1           2
----------- -----------
    5307596     2894135
 
  1 record(s) selected.
 
[db2inst1@prod db2inst1]$ db2 "select count(fin_id)/ count(distinct fin_iddos) from finan"
 
1
-----------
          1
 
  1 record(s) selected.


Normal que ça soit plus rapide :o :o  ( c'est un db2 V8.1FP8)


db2 => SELECT COUNT(idCochon)/COUNT(DISTINCT idUser) as nb_cochon_par_user  FROM
 cochons
 
NB_COCHON_PAR_USER
------------------
                 4
 
  1 record(s) selected.


et

db2 => select avg(cnt) from (select count(*) cnt from cochons group by iduser) a
s v1
 
1
-----------
          4
 
  1 record(s) selected.

Reply

Marsh Posté le 22-12-2006 à 12:22:13    

oui s'bon j'ai compris ou était ma boulette hein :o
Le test ramenait 1.96 et comme MagicBuzz l'a fort justement souligné, c'était casté en int donc ça affichait 1.
Du coup pour que ça affiche la vrai moyenne et pas la moyenne arrondi

SELECT CAST(COUNT(idCochon) as DECIMAL(14,4))/CAST(COUNT(DISTINCT idUser) as DECIMAL(14,4)) as nb_cochon_par_user  FROM
 cochons


edit:
Si tu fais un show optimized query des deux il te sort quoi?


Message édité par anapajari le 22-12-2006 à 12:23:11
Reply

Marsh Posté le 22-12-2006 à 12:54:04    

je ne dois faire aucun casting pour que ca m'affiche ca correctement.
 
EDIT :  
show optinized de SELECT COUNT(idCochon)/COUNT(DISTINCT idUser) as nb_cochon_par_user  FROM cochons donne  

SELECT (Q3.$C0 / Q3.$C1) AS "NB_COCHON_PAR_USER"  
FROM  
(SELECT COUNT(* ), COUNT(DISTINCT Q2.$C0)  
FROM  
(SELECT Q1.IDUSER  
FROM ARNAUD1.COCHONS AS Q1) AS Q2) AS Q3


cout : 320489 instructions CPU
 
et show optinized de select avg(cnt) from (select count(*) cnt from cochons group by iduser) as v1 donne  

SELECT (Q5.$C0 / Q5.$C1)  
FROM  
(SELECT SUM(Q4.$C0), COUNT(* )  
FROM  
(SELECT Q3.$C0  
FROM  
(SELECT COUNT(* )  
FROM  
(SELECT Q1.IDUSER  
FROM ARNAUD1.COCHONS AS Q1) AS Q2  
GROUP BY Q2.$C0) AS Q3) AS Q4) AS Q5


cout : 323834 instructions CPU


Message édité par polo021 le 22-12-2006 à 13:06:46
Reply

Marsh Posté le 22-12-2006 à 13:54:41    

donc c'est kif kif en fait ( 1% d'ecart )

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed