ORA-00979 n'est pas un groupe par expression

147

Je reçois 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 trouvé aucun exemple contenant des clauses GROUP BY et ORDER BY dans la même requête. J'ai essayé de supprimer chaque champ du groupe un par un, mais j'obtiens toujours la même erreur.

Il y a un
la source

Réponses:

232

Vous devez placer toutes les colonnes du SELECTdans GROUP BYou utiliser des fonctions sur celles-ci qui compressent les résultats en une seule valeur (comme MIN, MAXou SUM).

Un exemple simple pour comprendre pourquoi cela se produit: imaginez que vous avez 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à remplir, GROUP BYmais il y a maintenant deux valeurs de barà choisir. Quel résultat attendriez-vous - Aou B? Ou la base de données devrait-elle renvoyer plus d'une ligne, violant le contrat de GROUP BY?

Aaron Digulla
la source
7
Non, vous n'avez pas besoin de les mettre dans votre ordre par clause
Xaisoft
3
J'ai essayé d'ajouter les deux colonnes de ORDER BY au GROUP BY. Ça a marché. Merci!
Theresa
1
Ou pour le dire autrement: si vous avez deux colonnes et que vous groupez par la première, cela signifie que vous aurez plusieurs valeurs de la deuxième colonne par ligne de résultat. Puisqu'il n'y a qu'une seule ligne de résultat mais plusieurs valeurs parmi lesquelles choisir, laquelle doit renvoyer la base de données? Le premier sur lequel il tombe?
Aaron Digulla
6
@AaronDigulla C'est ce que fait MySQL, et le monde n'est pas terminé: p
Chris Baker
1
Je suis partiellement d'accord. Mais supposons le cas suivant: il y a 4 colonnes: A, B, C et D. Maintenant, je fixe (A, B, C) comme clé composite. Alors "sélectionner A, B, max (C), D ... grouper par A, B" n'est pas ambigu, puisque pour chaque combinaison de A, B et C, D est déjà défini. Oracle refuse toujours de faire son travail.
ga
17

Incluez dans la GROUP BYclause toutes les SELECTexpressions qui ne sont pas des arguments de fonction de groupe.

Xaisoft
la source
9

Dommage qu'Oracle ait des limitations comme celles-ci. Bien sûr, le résultat pour une colonne qui ne figure pas dans GROUP BY serait aléatoire, mais parfois vous le souhaitez. Silly Oracle, vous pouvez le faire dans MySQL / MSSQL.

MAIS il existe une solution pour Oracle:

Bien que 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 ce qui suit, pour garder votre colonne dans la portée, mais pas grouper par elle (en supposant que ce sont des 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);
Joseph Lust
la source
@GlennFromIowa étant donné que ma pseudo table n'est pas rigoureusement définie ci-dessus, et que je ne travaille plus pour une entreprise avec 11g, je ne peux pas fournir un meilleur exemple, même si c'était un problème lorsque je l'ai testé pour la dernière fois.
Joseph Lust
4
Juste par curiosité, quel est un exemple de cas où vous voudriez un résultat aléatoire? Je ne vois aucune raison pour laquelle vous voudriez grouper par FOO et obtenir une ligne aléatoire pour BAR.
Kyle Bridenstine
4

Si vous ne le regroupement en vertu d'inclure la GROUP BYclause, toute expression SELECT, ce qui est fonction de groupe (ou fonction d' agrégation ou d'une colonne agrégée) , tels que COUNT, AVG, MIN, MAX, SUMetc. ( Liste des fonctions d' agrégation ) doit être présent dans l' GROUP BYarticle.

Exemple (manière correcte) (ici employee_idn'est pas une fonction de groupe (colonne non agrégée), elle doit donc apparaître dans GROUP BY. En revanche, sum (salaire) est une fonction de groupe (colonne agrégée), il n'est donc pas nécessaire qu'elle apparaisse dans la GROUP BYclause .

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

Exemple (mauvaise manière) (ici employee_idn'est pas une fonction de groupe et elle n'apparaît pas dans la GROUP BYclause, ce qui entraînera l'erreur ORA-00979.

   SELECT employee_id, sum(salary) 
   FROM employees;

Pour corriger, vous devez effectuer l' une des opérations suivantes:

  • Inclure toutes les expressions non agrégées répertoriées dans la SELECTclause de la GROUP BYclause
  • Supprimer la fonction de groupe (agrégation) de la SELECTclause.
fg78nc
la source
2

Vous devez faire ce qui 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;
Pavel Zimogorov
la source
1

La même erreur survient également lorsque le mot clé UPPER ou LOWER n'est pas utilisé à la fois dans l'expression select et group by expression.

Faux :-

select a , count(*) from my_table group by UPPER(a) .

Droite :-

select UPPER(a) , count(*) from my_table group by UPPER(a) .
Opster Elasticsearch Pro-Vijay
la source
1

Le groupe par est utilisé pour agréger certaines données, en fonction de la fonction d'agrégation, et à part cela, vous devez placer la ou les colonnes dans lesquelles vous avez besoin du regroupement.

par exemple:

select d.deptno, max(e.sal) 
from emp e, dept d
where e.deptno = d.deptno
group by d.deptno;

Cela se traduira par le salaire maximum des départements.

Maintenant, si nous omettons la d.deptnoclause from group by, cela donnera la même erreur.

Muhammad Nadeem
la source
1

En plus des autres réponses, cette erreur peut se produire s'il y a une incohérence dans un ordre par clause. Par exemple:

select 
    substr(year_month, 1, 4)
    ,count(*) as tot
from
    schema.tbl
group by
    substr(year_month, 1, 4)
order by
    year_month
3pitt
la source