Bonjour,

J'aimerais bien avoir quelques explications sur ce genre d'erreurs ..
Par exemple, voici une requete :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$requete = "
SELECT 
vendeurs.nom, 
vendeurs.id_vendeur, 
dossiers.id_dossier, 
COUNT(id_dossier_vendeur.id_dossier) AS nb_dossier,
SUM(dossiers.total) AS ca_total
FROM
".$GLOBALS['prefixe'].".vendeurs,
".$GLOBALS['prefixe'].".id_dossier_vendeur,
".$GLOBALS['prefixe'].".dossiers
WHERE
vendeurs.id_vendeur = id_dossier_vendeur.id_vendeur
AND dossiers.id_dossier = id_dossier_vendeur.id_dossier
GROUP BY 
vendeurs.nom, 
vendeurs.id_vendeur
";

Si je tente cette requete, voici la reponse de postgres :
Warning: pg_query() [function.pg-query]: Query failed: ERROR: column "dossiers.id_dossier" must appear in the GROUP BY clause or be used in an aggregate function in /usr/local/apache/htdocs/scripts/V2/stats_vendeurs.php on line 109
ERROR: column "dossiers.id_dossier" must appear in the GROUP BY clause or be used in an aggregate function SELECT vendeurs.nom, vendeurs.id_vendeur, dossiers.id_dossier, COUNT(id_dossier_vendeur.id_dossier) AS nb_dossier, SUM(dossiers.total) AS ca_total FROM clients_dossiers.vendeurs, clients_dossiers.id_dossier_vendeur, clients_dossiers.dossiers WHERE vendeurs.id_vendeur = id_dossier_vendeur.id_vendeur AND dossiers.id_dossier = id_dossier_vendeur.id_dossier GROUP BY vendeurs.nom, vendeurs.id_vendeur

Par contre, si je supprime dossiers.id_dossier de mon select, ca passe impeccable..
Mais je ne vois pas pourquoi je suis obligé de faire passer dossiers.id_dossier dans le group by..

Postgres semble tres chatouilleux sur ce point la.. j'ai lu la doc sur le sujet, mais ca n'est pas tres clair..

La clause Clause GROUP BY est utilisée pour regrouper des lignes d'une table partageant les mêmes valeurs dans toutes les colonnes précisées. L'ordre dans lequel ces colonnes sont indiquées importe peu. L'effet est de combiner chaque ensemble de lignes partageant des valeurs communes en un seul groupe de ligne représentant toutes les lignes du groupe. Ceci se fait en éliminant les redondances dans la sortie et/ou pour calculer les agrégats s'appliquant à ces groupes. Par exemple :

=> SELECT * FROM test1;
x | y
---+---
a | 3
c | 2
b | 5
a | 1
(4 rows)

=> SELECT x FROM test1 GROUP BY x;
x
---
a
b
c
(3 rows)

Dans la seconde requête, nous n'aurions pas pu écrire SELECT * FROM test1 GROUP BY x parce qu'il n'existe pas une seule valeur pour la colonne y pouvant être associé avec chaque autre groupe. Les colonnes de regroupement peuvent être référencées dans la liste de sélection car elles ont une valeur constante unique par groupe.

En général, si une table est groupée, les colonnes qui ne sont pas utilisées dans le regroupement ne peuvent pas être référencées sauf dans les expressions d'agrégats. Voici un exemple d'expressions d'agrégat :

=> SELECT x, sum(y) FROM test1 GROUP BY x;
x | sum
---+-----
a | 4
b | 5
c | 2
(3 rows)

Ici, sum est la fonction d'agrégat qui calcule une seule valeur pour le groupe entier. Plus d'informations sur les fonctions d'agrégats disponibles sont proposées dans Section 9.15.

Astuce : Le regroupement sans expressions d'agrégats calcule effectivement l'ensemble les valeurs distinctes d'une colonne. Ceci peut aussi se faire en utilisant la clause DISTINCT (voir Section 7.3.3).

Voici un autre exemple : il calcule les ventes totales pour chaque produit (plutôt que le total des ventes sur tous les produits).

SELECT produit_id, p.nom, (sum(v.unite) * p.prix) AS ventes
FROM produits p LEFT JOIN ventes v USING (produit_id)
GROUP BY produit_id, p.nom, p.prix;

Dans cet exemple, les colonnes produit_id, p.nom et p.prix doivent être dans la clause GROUP BY car elles sont référencées dans la liste de sélection de la requête. (Suivant la façon dont est conçue la table produits, le nom et le prix pourraient être totalement dépendants de l'ID du produit, donc des regroupements supplémentaires pourraient théoriquement être inutiles mais ceci n'est pas encore implémenté.) La colonne s.unite n'a pas besoin d'être dans la liste GROUP BY car elle est seulement utilisée dans l'expression de l'agrégat (sum(...)) représentant les ventes d'un produit. Pour chaque produit, la requête renvoie une ligne de résumé sur les ventes de ce produit.

En SQL strict, GROUP BY peut seulement grouper les colonnes de la table source mais PostgreSQL étend ceci en autorisant GROUP BY à grouper aussi les colonnes de la liste de sélection. Grouper par expressions de valeurs au lieu de simples noms de colonnes est aussi permis.

Si une table a été groupée en utilisant la clause GROUP BY mais que seul certains groupes sont intéressants, la clause HAVING peut être utilisée, plus comme une clause WHERE, pour éliminer les groupes d'une table groupée. Voici la syntaxe :

SELECT liste_selection FROM ... [WHERE
...] GROUP BY ... HAVING
expression_booléenne

Les expressions de la clause HAVING peuvent référer à la fois aux expressions groupées et aux expressions non groupées (ce qui impliquent nécessairement une fonction d'agrégat).

Exemple :

=> SELECT x, sum(y) FROM test1 GROUP BY x HAVING sum(y) > 3;
x | sum
---+-----
a | 4
b | 5
(2 rows)

=> SELECT x, sum(y) FROM test1 GROUP BY x HAVING x < 'c';
x | sum
---+-----
a | 4
b | 5
(2 rows)

De nouveau, un exemple plus réaliste :

SELECT produit_id, p.nom, (sum(v.unite) * (p.prix - p.cout)) AS profit
FROM produits p LEFT JOIN ventes v USING (produit_id)
WHERE v.date > CURRENT_DATE - INTERVAL '4 weeks'
GROUP BY produit_id, p.nom, p.prix, p.cout
HAVING sum(p.prix * s.unite) > 5000;

Dans l'exemple ci-dessus, la clause WHERE sélectionne les lignes par une colonne qui n'est pas groupée (l'expression est vraie seulement pour les ventes des quatre dernières semaines) alors que la clause HAVING restreint la sortie aux groupes dont le total des ventes dépasse 5000. Notez que les expressions d'agrégats n'ont pas besoin d'être identiques dans toutes les parties d'une requête.

Et si j'essaye sans "Group by" .. dans l'espoir de recuperer tous les id_dossiers, il me sort aussi une erreur..
Warning: pg_query() [function.pg-query]: Query failed: ERROR: column "vendeurs.nom" must appear in the GROUP BY clause or be used in an aggregate function in /usr/local/apache/htdocs/scripts/V2/stats_vendeurs.php on line 106
ERROR: column "vendeurs.nom" must appear in the GROUP BY clause or be used in an aggregate function SELECT vendeurs.nom, vendeurs.id_vendeur, dossiers.id_dossier, COUNT(id_dossier_vendeur.id_dossier) AS nb_dossier, SUM(dossiers.total) AS ca_total FROM clients_dossiers.vendeurs, clients_dossiers.id_dossier_vendeur, clients_dossiers.dossiers WHERE vendeurs.id_vendeur = id_dossier_vendeur.id_vendeur AND dossiers.id_dossier = id_dossier_vendeur.id_dossier

Bref... c'est le COUNT qui oblige a tout grouper ? ou comment ca marche ..? j'arrive a passer outre ces limitations, mais j'aime bien comprendre les motifs ..