Précédent   Forum des professionnels en informatique > Bases de données > Oracle > SQL
SQL Forum d'entraide sur le SQL pour Oracle
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 20/06/2008, 10h54   #1
Futur Membre du Club
 
Inscription : avril 2005
Messages : 33
Détails du profil
Informations forums :
Inscription : avril 2005
Messages : 33
Points : 19
Points : 19
Par défaut GROUP BY et SELECT *

Bonjour à tous ,

Est-il possible de faire un select * avec une clause group by ?

Comme par exemple :
Code :
SELECT * FROM Table1 GROUP BY Champ1
Ou doit-on spécifier tous les champs dans le Select ?

Cordialement.
guiph est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/06/2008, 11h13   #2
Membre éprouvé
 
Avatar de chrifo
 
Inscription : juillet 2006
Messages : 445
Détails du profil
Informations forums :
Inscription : juillet 2006
Messages : 445
Points : 418
Points : 418
Bonjour,
Le problème n'est pas dans le select mais dans le group by, qui va vous demander plus de colonnes, selon les données de la table.
Pourquoi ne pas tout simplement faire un "distinct" ?
chrifo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/06/2008, 11h26   #3
Futur Membre du Club
 
Inscription : avril 2005
Messages : 33
Détails du profil
Informations forums :
Inscription : avril 2005
Messages : 33
Points : 19
Points : 19
Si j'utilise distinct je suis obligé d'écrire tous les champs dans ma requête comme par exemple :
Code :
SELECT DISTINCT Champ1, Champ2 ... champN
Donc le '*' ne fonctionnera pas d'avantage non ?
guiph est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/06/2008, 11h32   #4
Membre Expert
 
Avatar de pacmann
 
Homme Pacman Pacman
Business analyst
Inscription : juin 2004
Messages : 1 417
Détails du profil
Informations personnelles :
Nom : Homme Pacman Pacman
Âge : 31
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Business analyst
Secteur : Finance

Informations forums :
Inscription : juin 2004
Messages : 1 417
Points : 2 309
Points : 2 309
Salut !

Qu'essaies-tu d'obtenir ?
GROUP BY te permet de définir des groupes selon un certain critère (égalité sur champ1), afin de pouvoir appliquer des fonctions d'aggrégat sur ce groupe.
=> une seule ligne t'es retournée par valeur possible de champ1

Si tu demandes le champ2, quelle valeur va-t-on bien pouvoir te retourner, vu que ce n'est pas la même pour toutes les lignes du groupe ?

Si ce que tu veux, c'est obtenir les résultats d'agrégats reportés sur chaque ligne, essaie les fonction analytiques : OVER(PARTITION BY champ1)
__________________

(c'est ma photo)
Paku, Paku !
Pour les jeunes incultes : non, je ne suis pas un pokémon...

Le pacblog : http://pacmann.over-blog.com/
pacmann est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/06/2008, 11h35   #5
Membre éprouvé
 
Avatar de chrifo
 
Inscription : juillet 2006
Messages : 445
Détails du profil
Informations forums :
Inscription : juillet 2006
Messages : 445
Points : 418
Points : 418
Citation:
Envoyé par guiph Voir le message
Donc le '*' ne fonctionnera pas d'avantage non ?
Sisi, ça fonctionnera.

Attention : distinct et group by n'ont rien à voir, évitez d'utiliser un regroupement lorsque cela est inutile.
chrifo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/06/2008, 14h07   #6
Futur Membre du Club
 
Inscription : avril 2005
Messages : 33
Détails du profil
Informations forums :
Inscription : avril 2005
Messages : 33
Points : 19
Points : 19
Citation:
Envoyé par pacmann Voir le message
Salut !

Qu'essaies-tu d'obtenir ?
GROUP BY te permet de définir des groupes selon un certain critère (égalité sur champ1), afin de pouvoir appliquer des fonctions d'aggrégat sur ce groupe.
=> une seule ligne t'es retournée par valeur possible de champ1

Si tu demandes le champ2, quelle valeur va-t-on bien pouvoir te retourner, vu que ce n'est pas la même pour toutes les lignes du groupe ?

Si ce que tu veux, c'est obtenir les résultats d'agrégats reportés sur chaque ligne, essaie les fonction analytiques : OVER(PARTITION BY champ1)
Oui en fait je souhaite prendre une seule ligne par doublon, peut importe la valeurs des autres champs mais il faut que j'affiche une ligne. La première par exemple.

Je ne sais pas si j'ai été bien clair

Par contre je ne connais pas du tout les fonctions analytiques ...
guiph est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/06/2008, 14h33   #7
Membre éprouvé
 
Avatar de chrifo
 
Inscription : juillet 2006
Messages : 445
Détails du profil
Informations forums :
Inscription : juillet 2006
Messages : 445
Points : 418
Points : 418
De toutes manières avec les fonctions analytiques vous allez devoir traiter chaque champ.
Peut-être l'utilisation du rownum peut vous être utile :
Code :
1
2
3
4
5
 
SELECT Table1.* 
FROM  
  (SELECT rownum numrow, Table1.* FROM Table1) Table1
  INNER JOIN (SELECT min(rownum) numrow, Champ1 FROM Table1 GROUP BY Champ1) T1 ON Table1.numrow = T1.numrow AND Table1.Champ1 = T1.Champ1
chrifo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/06/2008, 16h08   #8
Futur Membre du Club
 
Inscription : avril 2005
Messages : 33
Détails du profil
Informations forums :
Inscription : avril 2005
Messages : 33
Points : 19
Points : 19
Merci pour vos bonnes idées
guiph est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/06/2008, 16h13   #9
Expert Confirmé
 
Avatar de 7gyY9w1ZY6ySRgPeaefZ
 
Homme
dba
Inscription : juillet 2007
Messages : 2 523
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : Canada

Informations professionnelles :
Activité : dba

Informations forums :
Inscription : juillet 2007
Messages : 2 523
Points : 3 975
Points : 3 975
Citation:
Envoyé par guiph Voir le message
Est-il possible de faire un select * avec une clause group by ?
Par principe, ce n'est jamais une bonne idée de faire un select * et ça ne coûte pas plus cher d'écrire tous les champs, même si ça peut faire lourd.
Une modification de ta table et ta requète peut te renvoyer des résultats bizarres.
Et pour trouver la source de ce genre d'erreurs, c'est plutôt chronophage.
7gyY9w1ZY6ySRgPeaefZ est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/06/2008, 10h07   #10
Expert Confirmé Sénior


 
Avatar de laurentschneider
 
Homme Laurent Schneider
Administrateur de base de données
Inscription : décembre 2005
Messages : 2 927
Détails du profil
Informations personnelles :
Nom : Homme Laurent Schneider
Localisation : Suisse

Informations professionnelles :
Activité : Administrateur de base de données
Secteur : Finance

Informations forums :
Inscription : décembre 2005
Messages : 2 927
Points : 4 549
Points : 4 549
Citation:
Envoyé par chrifo Voir le message
De toutes manières avec les fonctions analytiques vous allez devoir traiter chaque champ.
Peut-être l'utilisation du rownum peut vous être utile :
Code :
1
2
3
4
5
6
7
 
SELECT Table1.* 
FROM  
  (SELECT rownum numrow, Table1.* FROM Table1) Table1
INNER JOIN (SELECT min(rownum) numrow, Champ1 FROM Table1
  GROUP BY Champ1) T1 
ON Table1.numrow = T1.numrow AND Table1.Champ1 = T1.Champ1
Vraiment intéressant comme approche.

Bon, tu auras quand même "rownum" dans la sélection. Donc, le * ne fonctionne pas, il te faudrait un "* mais pas rownum".

Aussi tu t'es pas sur que le rownum de T1 corresponde au rownum de Table1, suivant le plan rownum pourrait ne pas correspondre aux même lignes.

Pour éviter ceci j'utiliserais donc

Code :
1
2
SELECT * FROM emp WHERE (empno,deptno) IN 
  (SELECT max(empno),deptno FROM emp GROUP BY deptno)
Avec EMPNO clé primaire
__________________
Mon blog : laurentschneider.com
Mon livre : Advanced Oracle SQL Programming
laurentschneider est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/06/2008, 10h08   #11
Expert Confirmé Sénior


 
Avatar de laurentschneider
 
Homme Laurent Schneider
Administrateur de base de données
Inscription : décembre 2005
Messages : 2 927
Détails du profil
Informations personnelles :
Nom : Homme Laurent Schneider
Localisation : Suisse

Informations professionnelles :
Activité : Administrateur de base de données
Secteur : Finance

Informations forums :
Inscription : décembre 2005
Messages : 2 927
Points : 4 549
Points : 4 549
Citation:
Envoyé par Jerome_Mtl Voir le message
Par principe, ce n'est jamais une bonne idée de faire un select *
Tout à faire d'accord, ce n'est en principe pas une bonne idée, surtout quand on fait ça par paresse
__________________
Mon blog : laurentschneider.com
Mon livre : Advanced Oracle SQL Programming
laurentschneider est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 24/06/2008, 09h14   #12
Membre éprouvé
 
Avatar de chrifo
 
Inscription : juillet 2006
Messages : 445
Détails du profil
Informations forums :
Inscription : juillet 2006
Messages : 445
Points : 418
Points : 418
Citation:
Envoyé par laurentschneider Voir le message
Aussi tu t'es pas sur que le rownum de T1 corresponde au rownum de Table1, suivant le plan rownum pourrait ne pas correspondre aux même lignes.
Arghh, je te crois sur parole et mes noms d'alias étaient maladroits, mais je pensais que le fait de "pré-sélectionner" mes rownums comme je l'ai fait dans les deux sous-requêtes me mettrait à l'abri du problème.
chrifo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 24/06/2008, 16h50   #13
Expert Confirmé Sénior


 
Avatar de laurentschneider
 
Homme Laurent Schneider
Administrateur de base de données
Inscription : décembre 2005
Messages : 2 927
Détails du profil
Informations personnelles :
Nom : Homme Laurent Schneider
Localisation : Suisse

Informations professionnelles :
Activité : Administrateur de base de données
Secteur : Finance

Informations forums :
Inscription : décembre 2005
Messages : 2 927
Points : 4 549
Points : 4 549
bon, je vois, il va falloir te trouver une démo ...

excuse-moi si c'est un peu brouillon, c'était pas si simple de trouver un cas où ca ne marche pas.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
SQL> col x FOR a10 tru
SQL> col x_1 FOR a10 tru
SQL> col z FOR a10 tru
SQL> CREATE TABLE t(x varchar2(4000), y number, z varchar2(4000))
TABLE created.
SQL> INSERT INTO t VALUES (lpad('c',4000,'c'), 4, lpad('z',4000,'z'))
1 row created.
SQL> INSERT INTO t VALUES (lpad('c',4000,'c'), 4, lpad('z',4000,'z'))
1 row created.
SQL> INSERT INTO t VALUES (lpad('a',4000,'a'), 1, lpad('z',4000,'z'))
1 row created.
SQL> INSERT INTO t VALUES (lpad('a',4000,'a'), 2, lpad('z',4000,'z'))
1 row created.
SQL> INSERT INTO t VALUES (lpad('b',4000,'b'), 3, lpad('z',4000,'z'))
1 row created.
SQL> INSERT INTO t VALUES (lpad('b',4000,'b'), 4, lpad('z',4000,'z'))
1 row created.
SQL> INSERT INTO t VALUES (lpad('b',4000,'b'), 5, lpad('z',4000,'z'))
1 row created.
SQL> INSERT INTO t VALUES (lpad('b',4000,'b'), 6, lpad('z',4000,'z'))
1 row created.
SQL> INSERT INTO t VALUES (lpad('b',4000,'b'), 7, lpad('z',4000,'z'))
1 row created.
SQL> INSERT INTO t VALUES (lpad('b',4000,'b'), 8, lpad('z',4000,'z'))
1 row created.
SQL> INSERT INTO t VALUES (lpad('b',4000,'b'), 9, lpad('z',4000,'z'))
1 row created.
SQL> INSERT INTO t VALUES (lpad('b',4000,'b'), 10, lpad('z',4000,'z'))
1 row created.
SQL> INSERT INTO t VALUES (lpad('b',4000,'b'), 11, lpad('z',4000,'z'))
1 row created.
SQL> commit
Commit complete.
SQL> CREATE OR REPLACE VIEW v AS SELECT x,y,z FROM t WHERE y<15
VIEW created.
SQL> SELECT rownum, v.* FROM v
 
    ROWNUM X                   Y Z         
---------- ---------- ---------- ----------
         1 cccccccccc          4 zzzzzzzzzz
         2 cccccccccc          4 zzzzzzzzzz
         3 aaaaaaaaaa          1 zzzzzzzzzz
         4 aaaaaaaaaa          2 zzzzzzzzzz
         5 bbbbbbbbbb          3 zzzzzzzzzz
         6 bbbbbbbbbb          4 zzzzzzzzzz
         7 bbbbbbbbbb          6 zzzzzzzzzz
         8 bbbbbbbbbb          8 zzzzzzzzzz
         9 bbbbbbbbbb          7 zzzzzzzzzz
        10 bbbbbbbbbb          5 zzzzzzzzzz
        11 bbbbbbbbbb          9 zzzzzzzzzz
        12 bbbbbbbbbb         10 zzzzzzzzzz
        13 bbbbbbbbbb         11 zzzzzzzzzz
 
 
13 rows selected.
SQL> SELECT x,min(rownum) FROM v GROUP BY x
 
X          MIN(ROWNUM)
---------- -----------
cccccccccc           1
bbbbbbbbbb           5
aaaaaaaaaa           3
 
 
3 rows selected.
SQL> CREATE INDEX i ON t(y,x) compute statistics
INDEX created.
SQL> analyze TABLE t compute statistics
TABLE analyzed.
SQL> SELECT rownum, v.* FROM v
 
    ROWNUM X                   Y Z         
---------- ---------- ---------- ----------
         1 cccccccccc          4 zzzzzzzzzz
         2 cccccccccc          4 zzzzzzzzzz
         3 aaaaaaaaaa          1 zzzzzzzzzz
         4 aaaaaaaaaa          2 zzzzzzzzzz
         5 bbbbbbbbbb          3 zzzzzzzzzz
         6 bbbbbbbbbb          4 zzzzzzzzzz
         7 bbbbbbbbbb          6 zzzzzzzzzz
         8 bbbbbbbbbb          8 zzzzzzzzzz
         9 bbbbbbbbbb          7 zzzzzzzzzz
        10 bbbbbbbbbb          5 zzzzzzzzzz
        11 bbbbbbbbbb          9 zzzzzzzzzz
        12 bbbbbbbbbb         10 zzzzzzzzzz
        13 bbbbbbbbbb         11 zzzzzzzzzz
 
 
13 rows selected.
SQL> SELECT min(rownum),x FROM v GROUP BY x
 
MIN(ROWNUM) X         
----------- ----------
          3 bbbbbbbbbb
          5 cccccccccc
          1 aaaaaaaaaa
 
 
3 rows selected.
SQL> SELECT * 
FROM  
  (SELECT rownum numrow, v.* FROM v) Table1
  INNER JOIN (SELECT min(rownum) numrow, x FROM v GROUP BY x) T1 
  ON Table1.numrow = T1.numrow AND Table1.x = T1.x
no rows selected.
SQL> DROP INDEX i
INDEX dropped.
SQL> SELECT * 
FROM  
  (SELECT rownum numrow, v.* FROM v) Table1
  INNER JOIN (SELECT min(rownum) numrow, x FROM v GROUP BY x) T1 
  ON Table1.numrow = T1.numrow AND Table1.x = T1.x
 
    NUMROW X                   Y Z            NUMROW_1 X_1       
---------- ---------- ---------- ---------- ---------- ----------
         1 cccccccccc          4 zzzzzzzzzz          1 cccccccccc
         3 aaaaaaaaaa          1 zzzzzzzzzz          3 aaaaaaaaaa
         5 bbbbbbbbbb          3 zzzzzzzzzz          5 bbbbbbbbbb
 
 
3 rows selected.
__________________
Mon blog : laurentschneider.com
Mon livre : Advanced Oracle SQL Programming
laurentschneider est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 24/06/2008, 17h41   #14
Membre éprouvé
 
Avatar de chrifo
 
Inscription : juillet 2006
Messages : 445
Détails du profil
Informations forums :
Inscription : juillet 2006
Messages : 445
Points : 418
Points : 418
Ok je vois mieux le problème, effectivement c'est un peu difficile à reproduire mais le problème est bien là, donc méthode à éviter.

Merci beaucoup pour la démo !
chrifo est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 02h50.


 
 
 
 
Partenaires

Hébergement Web