group by sur un champ contenant des valeurs null sous oracle

group by sur un champ contenant des valeurs null sous oracle - SQL/NoSQL - Programmation

Marsh Posté le 02-10-2006 à 15:15:41    

Bonjour,
j'ai un petit probleme  lorsque je veux faire la requette suivante car elle ne me retourne pas les champs null
 
Select no_archive, count(no_archive) from matable
group by no_archive;
 
voila le resultat retourne :
 
 120 47260
 121 46400
 122 12630
 123 24964
 124 31428
 125 20839
  0
 
or les enregistrements ayant no_archive = null sont les plus nombreux
 
comment faire? merci


Message édité par crashman le 02-10-2006 à 16:41:29
Reply

Marsh Posté le 02-10-2006 à 15:15:41   

Reply

Marsh Posté le 02-10-2006 à 16:21:55    

salut,  
 
essaye GROUP BY ALL no_archive
 
c'est de la syntaxe Microsoft mais ça devrait marcher sur Oracle, enfin espérons... :)  
http://msdn2.microsoft.com/en-us/library/ms177673.aspx

Reply

Marsh Posté le 02-10-2006 à 16:40:35    

l'espoir etait pas au rendez-vous hélas ...
merci zebix !
si quelqu'un connait l'équivalent sous oracle ca me serait utile merci
 

Reply

Marsh Posté le 02-10-2006 à 16:59:59    

Bon je poserai la question à un dbA oracle de ma boîte demain hihi
 
Pour être sûr que j'aie bien compris, ce que tu cherches à avoir c'est un output du genre, c'est-ce pas ? :
 
 120 47260
 121 46400
 122 12630
 123 24964
 124 31428
 125 20839
 null 1649877  
 

Reply

Marsh Posté le 02-10-2006 à 17:04:16    

oe exactement !  
les champs null me pose pas mal de pb , meme sur les jointure du type :  
 
select a.*, b* from table1 a , table2 b  
where
a.no_archive = b.no_archive
and a.id=b.id
 
ca me sort pas les enregistrements lorsque ca matche mais que le no_archive est null
si ton bda avais la reponse à ce mystere ca me sauverai pas mal ! merci zebix

Message cité 2 fois
Message édité par crashman le 02-10-2006 à 19:18:10
Reply

Marsh Posté le 02-10-2006 à 18:01:48    

Pourquoi comptes-tu 'no_archive' ???
COUNT sur la valeur nulle renvoie 0 ...
 
Fais plutôt :
 

Code :
  1. Select no_archive, count(*)
  2. from matable
  3. group by no_archive;

Reply

Marsh Posté le 02-10-2006 à 18:34:49    

Beegee a écrit :

Pourquoi comptes-tu 'no_archive' ???
COUNT sur la valeur nulle renvoie 0 ...


+1  :jap:  
 

crashman a écrit :

oe exactement !  
les champs null me pose pas mal de pb , meme sur les jointure du type :  
 
select a.*, b* from table1 a , table1 b  
where
a.no_archive = b.no_archive
and a.id=b.id
 
ca me sort pas les enregistrements lorsque ca matche mais que le no_archive est null
si ton bda avais la reponse à ce mystere ca me sauverai pas mal ! merci zebix


 [:roane]  Apprends les bases du sql ( jointures externes ça te parle pas?) avant de parler de problèmes...
 
edit: j'avais même pas vu que tu jointais ta table sur elle même [:pingouino] mais ça change rien sur les jointures ...

Message cité 1 fois
Message édité par anapajari le 02-10-2006 à 18:36:30
Reply

Marsh Posté le 02-10-2006 à 19:17:25    

anapajari a écrit :

+1  :jap:  
 
 
 [:roane]  Apprends les bases du sql ( jointures externes ça te parle pas?) avant de parler de problèmes...
 
edit: j'avais même pas vu que tu jointais ta table sur elle même [:pingouino] mais ça change rien sur les jointures ...


 
salut anapajari, pour de raison de simplification j'ai volontairement mis une requete avec des jointures simples
donc il faut lire :
 
select a.*, b* from table1 a , table2 b  
where  
a.no_archive = b.no_archive  
and a.id=b.id  
 
je ne veux pas faire une jointure externe !  
et je connais les bases de sql merci !

Reply

Marsh Posté le 02-10-2006 à 19:28:57    

Beegee a écrit :

Pourquoi comptes-tu 'no_archive' ???
COUNT sur la valeur nulle renvoie 0 ...
 
Fais plutôt :
 

Code :
  1. Select no_archive, count(*)
  2. from matable
  3. group by no_archive;



 
 
en effet ca ca marche merci !
mais je n'arrive pas a comprendre la logique ... pourquoi les null ne sont pas comptable ?
il me semble que cela fonctionne en tsql ?
 
merci


Message édité par crashman le 02-10-2006 à 19:37:18
Reply

Marsh Posté le 03-10-2006 à 09:40:01    

La solution en Count(*) fonctionne ici pour l'exemple simplifié ici mais elle est non seulement peu performante si la table réelle a un plus grand nombre de champs (ce que je suppute) mais en plus il suffit qu'un tuple n'ait que des valeurs nulles et le count(*) ne le comptera pas de la même manière qu'il ne comptait pas "no_archive" quand celui-ci est null. Ce n'est pas fiable.  
 
J'ai eu la réponse de mon dbA Oracle au passage : l'erreur de base c'est d'avoir permis les null pour ton champ no_archive. Il vaut mieux prévoir une valeur "0", voire négative si "0" a un sens pour ton champ, qu'un null, lorsque tu as justement besoin de prendre en compte les occurences "vides" ...  
 
Quoi qu'il en soit la solution se trouve dans l'utilisation de la fonction NVL.


Message édité par ZeBix le 03-10-2006 à 09:48:27
Reply

Marsh Posté le 03-10-2006 à 09:40:01   

Reply

Marsh Posté le 03-10-2006 à 09:46:39    

Le count(*) n'a pas d'influence particulière sur les performances, c'est une idée préconçue due à des impacts sur les performances de très anciennes versions de certains SGBD.
 
Maintenant, un petit test rapide montre que count(*) fais bien ce que l'on veut, càd compter les lignes d'une table, quel que soit le contenu :
 

Code :
  1. create table test
  2. (champ1 number(9),
  3. champ2 number(9));
  4. insert into test values (1, 1);
  5. insert into test values (null, null);
  6. insert into test values (null, 1);
  7. select count(champ1) from test;
  8. => 1
  9. select count(champ2) from test;
  10. => 2
  11. select count(*) from test;
  12. => 3

Reply

Marsh Posté le 03-10-2006 à 09:51:59    

Beegee a écrit :

Le count(*) n'a pas d'influence particulière sur les performances, c'est une idée préconçue due à des impacts sur les performances de très anciennes versions de certains SGBD.


 
Source ?  
 
J'ai fait des tests sur MySQL 4.1, qui n'est certes pas le plus récent mais qui est loin d'être une version "très anciennes".
 
Et sur des croisements de tables volumineuses, la performance va du simple au double, cf. le link dans mon message édité ci-dessus, vers un topic où j'en parle sur hardware.fr
 
 
Quant au Count(*) qui ne compte pas les tuples null, au temps pour moi  :jap:

Reply

Marsh Posté le 03-10-2006 à 09:58:24    

Je cite une des bibles concernant Oracle, le site AskTom :
 
http://asktom.oracle.com/pls/ask/f [...] 159920245,
 
edit: et si mySql n'est toujours pas capable de d'utiliser le même explain plan pour faire un count(*) ou un count(1) ... lol !  :pt1cable:  
Surtout que le plus lisible et le plus logique est bien le count(*).

Message cité 1 fois
Message édité par Beegee le 03-10-2006 à 09:59:27
Reply

Marsh Posté le 03-10-2006 à 09:59:21    

crashman a écrit :

oe exactement !  
les champs null me pose pas mal de pb , meme sur les jointure du type :  
select a.*, b* from table1 a , table2 b  
where
a.no_archive = b.no_archive
and a.id=b.id
ca me sort pas les enregistrements lorsque ca matche mais que le no_archive est null


 

crashman a écrit :

salut anapajari, pour de raison de simplification j'ai volontairement mis une requete avec des jointures simples
donc il faut lire :
select a.*, b* from table1 a , table2 b  
where  
a.no_archive = b.no_archive  
and a.id=b.id  
je ne veux pas faire une jointure externe !  
et je connais les bases de sql merci !


[:quardelitre]


Message édité par anapajari le 03-10-2006 à 10:00:23
Reply

Marsh Posté le 03-10-2006 à 10:07:57    

Beegee a écrit :

Je cite une des bibles concernant Oracle, le site AskTom :
 
http://asktom.oracle.com/pls/ask/f [...] 159920245,


 
Merci Tom :  
 

Citation :

select count(*)
from
 all_objects
 
 
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.02       0.02          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        2      5.56       5.56          0     234998          4           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4      5.58       5.58          0     234998          4           1
 
select count(1)
from
 all_objects
 
 
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.02       0.02          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        2      5.46       5.47          0     234998          4           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4      5.48       5.49          0     234998          4           1


 
Et il ne fait la requête que sur ~230k rows ...  
 

Citation :

Surtout que le plus lisible et le plus logique est bien le count(*).


 
Je ne vois pas ce qu'il y a de plus lisible et plus logique entre un count(*) et un count(1), ça devient du prosélytisme là  :sweat:  

Reply

Marsh Posté le 03-10-2006 à 11:07:23    

J'ai pas tout suivi.
Hier je bossais pas (Kipour du coup ma boîte fermée).
Et je débarque un peu là.
 
Vous en êtes où ?
C'est quoi la question exacte en faite ? Faut pas compter les valeurs nulles ?
 
Pkoi y'a pas une seule proposition : "where champ is not null" alors ?
A l'inverse, s'il faut inclure dans le champ les valeurs nulles "count(isnull(dtc, 0))"
 
M'enfin c'est un peu trop évident pour être la solution... Vous pouvez reposer la question plus clairement, et dire où vous en êtes là ?


Message édité par MagicBuzz le 03-10-2006 à 11:08:06
Reply

Marsh Posté le 03-10-2006 à 11:30:58    

Zebix:
 
Les explain plans sont les mêmes, les temps d'exécution sont similaires.
 
En pratique évidemment, les temps d'exécution sont légèrement différents, mais ça tient au fait que certains objets sont mis en cache par la première requête ... dont profite la seconde !
 
Enfin, COUNT(*) me parait plus logique, ça veut dire "compter les enregistrements". COUNT(expression) veut dire compter les occurrences non nulles de l'expression (donc COUNT(1) veut dire compter le nombre de fois que 1 est non null ...).
 
 
MagicBuzz:
 
L'auteur voulait simplement compter pour chaque no_archive (même null) le nombre de lignes ... il ne savait pas que la fonction COUNT compte les expressions non nulles. Il lui fallait donc utiliser COUNT(*) par exemple.
 
Ensuite ça a dégénéré sur le mythe entre la différence de perfs entre COUNT(*) et COUNT(1) (sur un SGBD de ce nom ...).

Message cité 1 fois
Message édité par Beegee le 03-10-2006 à 11:32:50
Reply

Marsh Posté le 03-10-2006 à 11:52:36    

de toute façon, rien ne vaut un SUM(1) :D

Reply

Marsh Posté le 03-10-2006 à 14:22:13    

Beegee a écrit :

Enfin, COUNT(*) me parait plus logique, ça veut dire "compter les enregistrements". COUNT(expression) veut dire compter les occurrences non nulles de l'expression (donc COUNT(1) veut dire compter le nombre de fois que 1 est non null ...).


 
Ok je vois ...
 
Dernière chose : sur un point théorique, Count(*) en SQL pur , ne compte PAS les tuples nuls, puisque le "*" désigne tous les champs, et si tous les champs sont nuls ben il ne les prend pas.
 
On a tous oublié de mentionner le champ "rowid", qui existe dans toute table Oracle, caché, et qui identifie de manière unique chaque tuple.
 
Donc la solution la plus optimale pour le problème de crashman est bien celle de beegee, à un point près c'est la colonne sélectionnée :  
 

Code :
  1. Select no_archive, count(rowid)
  2. from matable
  3. group by no_archive;


 
 :jap:

Message cité 1 fois
Message édité par ZeBix le 03-10-2006 à 14:23:28
Reply

Marsh Posté le 03-10-2006 à 14:24:23    

sum(1) ça marche aussi bien dans ce cas (le count(1) aussi vous me direz). le rowid ne me semble pas plus intéressant que la constante 1 dans ce cas. après c'est comme chacun sent, puisque le résultat sera le même pour des performances quasi identiques.

Reply

Marsh Posté le 03-10-2006 à 15:10:31    

Merci tout le monde pour les reponses,au moins  j'aurai le choix entre les sum(1) , count(rowid). count(1) :)
pensait pas  que la valeur null puisse poser autant de probleme ...
NVL est mon nouvel ami ... merci a zebix !

Reply

Marsh Posté le 03-10-2006 à 17:36:37    

ZeBix a écrit :

Ok je vois ...
 
Dernière chose : sur un point théorique, Count(*) en SQL pur , ne compte PAS les tuples nuls, puisque le "*" désigne tous les champs, et si tous les champs sont nuls ben il ne les prend pas.
 
On a tous oublié de mentionner le champ "rowid", qui existe dans toute table Oracle, caché, et qui identifie de manière unique chaque tuple.
 
Donc la solution la plus optimale pour le problème de crashman est bien celle de beegee, à un point près c'est la colonne sélectionnée :  
 

Code :
  1. Select no_archive, count(rowid)
  2. from matable
  3. group by no_archive;


 
 :jap:


 
Soit dit en passant, COUNT(constante) ou COUNT(rowid) est traduit en COUNT(*) sous Oracle, donc peu importe ;)

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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