185 votes

ORA-00979 pas un groupe par expression

J'obtiens ORA-00979 avec la requête suivante :

SELECT cr.review_sk, cr.cs_sk, cr.full_name,
tolist(to_char(cf.fact_date, 'mm/dd/yyyy')) "appt",
cs.cs_id, cr.tracking_number
from review cr, cs, fact cf
where cr.cs_sk = cs.cs_sk
and UPPER(cs.cs_id) like '%' || UPPER(i_cs_id) || '%'
and row_delete_date_time is null
and cr.review_sk = cf.review_wk (+)
and cr.fact_type_code (+) = 183050
GROUP BY cr.review_sk, cr.cs_sk, cf.fact_date, cr.tracking_number
ORDER BY cs.cs_id, cr.full_name;

Je n'ai pas trouvé d'exemples contenant des clauses GROUP BY et ORDER BY dans la même requête. J'ai essayé de supprimer chaque champ du group by, un par un, mais j'obtiens toujours la même erreur.

275voto

Aaron Digulla Points 143830

Vous devez placer toutes les colonnes du SELECT dans le GROUP BY ou utiliser des fonctions qui compriment les résultats en une seule valeur (comme MIN , MAX o SUM ).

Un exemple simple pour comprendre pourquoi cela se produit : Imaginez que vous ayez une base de données comme celle-ci :

FOO BAR
0   A
0   B

et vous courez SELECT * FROM table GROUP BY foo . Cela signifie que la base de données doit renvoyer une seule ligne comme résultat avec la première colonne 0 pour remplir la GROUP BY mais il y a maintenant deux valeurs de bar à choisir. Quel résultat attendez-vous - A o B ? Ou bien la base de données doit-elle renvoyer plus d'une ligne, violant ainsi le contrat de GROUP BY ?

23voto

Xaisoft Points 12363

Inclure dans le GROUP BY clause tous SELECT qui ne sont pas des arguments de fonction de groupe.

9voto

Joseph Lust Points 4961

Dommage qu'Oracle ait de telles limitations. Bien sûr, le résultat pour une colonne qui n'est pas dans le GROUP BY serait aléatoire, mais c'est parfois ce que l'on souhaite. Idiot d'Oracle, vous pouvez faire cela dans MySQL/MSSQL.

MAIS il existe une solution de contournement pour Oracle :

La ligne suivante ne fonctionne pas

SELECT unique_id_col, COUNT(1) AS cnt FROM yourTable GROUP BY col_A;

Vous pouvez tromper Oracle avec des 0 comme ceux qui suivent, pour garder votre colonne dans la portée, mais sans grouper par elle (en supposant qu'il s'agisse de nombres, sinon utilisez CONCAT).

SELECT MAX(unique_id_col) AS unique_id_col, COUNT(1) AS cnt 
FROM yourTable GROUP BY col_A, (unique_id_col*0 + col_A);

7voto

fg78nc Points 2371

Si vous effectuez un regroupement en vertu de l'inclusion de GROUP BY toute expression dans la clause SELECT qui n'est pas une fonction de groupe (ou une fonction agrégée ou une colonne agrégée) telle que COUNT , AVG , MIN , MAX , SUM et ainsi de suite ( Liste des fonctions agrégées ) doit être présent dans les GROUP BY clause.

Exemple (manière correcte) (ici employee_id n'est pas une fonction de groupe (colonne non agrégée). doit apparaissent dans GROUP BY . En revanche, sum(salary) est une fonction de groupe (colonne agrégée), qui n'a donc pas besoin d'apparaître dans le tableau de bord. GROUP BY clause.

   SELECT employee_id, sum(salary) 
   FROM employees
   GROUP BY employee_id; 

Exemple (mauvaise manière) (ici employee_id n'est pas une fonction de groupe et n'apparaît pas dans les GROUP BY ce qui conduira à l'erreur ORA-00979 .

   SELECT employee_id, sum(salary) 
   FROM employees;

Pour corriger la situation, vous devez procéder comme suit un des éléments suivants :

  • Inclure toutes les expressions non agrégées énumérées dans la rubrique SELECT de la clause de GROUP BY clause
  • Supprimer la fonction de groupe (agrégat) de SELECT clause.

3voto

Pavel Zimogorov Points 1151

Vous devez procéder comme suit :

SELECT cr.review_sk, 
       cr.cs_sk, 
       cr.full_name,
       tolist(to_char(cf.fact_date, 'mm/dd/yyyy')) "appt",
       cs.cs_id, 
       cr.tracking_number
from review cr, cs, fact cf
where cr.cs_sk = cs.cs_sk
       and UPPER(cs.cs_id) like '%' || UPPER(i_cs_id) || '%'
       and row_delete_date_time is null
       and cr.review_sk = cf.review_wk (+)
       and cr.fact_type_code (+) = 183050
GROUP BY cr.review_sk, cr.cs_sk, cf.fact_date, cr.tracking_number, cs.cs_id, cr.full_name
ORDER BY cs.cs_id, cr.full_name;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X