ORA-00979 non un gruppo per espressione


147

Ricevo ORA-00979 con la seguente query:

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;

Non sono riuscito a trovare alcun esempio che contenesse entrambe le clausole GROUP BY e ORDER BY nella stessa query. Ho provato a rimuovere ogni campo dal gruppo uno alla volta, ma sto ancora ottenendo lo stesso errore.

Risposte:


232

È necessario inserire tutte le colonne di SELECTin GROUP BYo utilizzare funzioni su di esse che comprimono i risultati su un singolo valore (come MIN, MAXo SUM).

Un semplice esempio per capire perché questo accada: immagina di avere un database come questo:

FOO BAR
0   A
0   B

e corri SELECT * FROM table GROUP BY foo. Ciò significa che il database deve restituire una singola riga come risultato con la prima colonna 0per soddisfare il GROUP BYma ora ci sono due valori tra cui barscegliere. Quale risultato ti aspetti - Ao B? O il database dovrebbe restituire più di una riga, violando il contratto di GROUP BY?


7
No, non è necessario inserirli nell'ordine in base alla clausola
Xaisoft,

3
Ho provato ad aggiungere le due colonne in ORDER BY a GROUP BY. Ha funzionato Grazie!
Theresa,

1
O per dirla in altro modo: se hai due colonne e raggruppa per la prima, ciò significa che avrai diversi valori dalla seconda colonna per riga di risultato. Poiché esiste solo una riga di risultati ma molti valori tra cui scegliere, quale dovrebbe restituire il DB? Il primo su cui si imbatte?
Aaron Digulla,

6
@AaronDigulla Ecco cosa fa MySQL e il mondo non è finito: p
Chris Baker,

1
Sono parzialmente d'accordo. Ma supponiamo il caso seguente: ci sono 4 colonne: A, B, C e D. Ora ho impostato (A, B, C) come chiave composita. Quindi "selezionare A, B, max (C), D ... gruppo per A, B" non è ambiguo, poiché per ogni combinazione di A, B e C, D è già definito. L'oracolo rifiuta di fare il suo lavoro.
ga

17

Includi nella GROUP BYclausola tutte le SELECTespressioni che non sono argomenti di funzioni di gruppo.


9

Peccato che Oracle abbia dei limiti come questi. Certo, il risultato per una colonna non presente in GROUP BY sarebbe casuale, ma a volte lo desideri. Silly Oracle, puoi farlo in MySQL / MSSQL.

MA c'è un modo per aggirare Oracle:

Mentre la seguente riga non funziona

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

Puoi ingannare Oracle con alcuni 0 come il seguente, per mantenere la colonna nell'ambito, ma non raggruppare per essa (supponendo che questi siano numeri, altrimenti usa 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);

@GlennFromIowa dato che il mio pseudo tavolo non è rigorosamente definito sopra e che non lavoro più per un'azienda con 11g, non posso fornire un esempio migliore, sebbene sia stato un problema quando l'ho provato l'ultima volta.
Joseph Lust,

4
Solo per curiosità, qual è un esempio di quando vorresti un risultato casuale? Non riesco a pensare a nessun motivo per cui vorresti raggrupparti per FOO e ottenere una riga casuale per BAR.
Kyle Bridenstine,

4

Se il raggruppamento in virtù di includere GROUP BYclausola, qualsiasi espressione in SELECT, che non è funzione di gruppo (o funzione di aggregazione o colonna aggregati) come COUNT, AVG, MIN, MAX, SUMe così via ( Elenco delle funzioni aggregate ) dovrebbe essere presente in GROUP BYclausola.

Esempio (modo corretto) (qui employee_idnon è una funzione di gruppo (colonna non aggregata), quindi deve apparire in GROUP BY. Al contrario, somma (stipendio) è una funzione di gruppo (colonna aggregata), quindi non è necessario che appaia nella GROUP BYclausola .

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

Esempio (modo sbagliato) (qui employee_idnon è una funzione di gruppo e non appare nella GROUP BYclausola, che porterà all'errore ORA-00979.

   SELECT employee_id, sum(salary) 
   FROM employees;

Per correggere è necessario effettuare una delle seguenti operazioni:

  • Includi tutte le espressioni non aggregate elencate nella SELECTclausola nella GROUP BYclausola
  • Rimuovi la funzione di gruppo (aggregato) dalla SELECTclausola.

2

Dovresti fare quanto segue:

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;

1

Lo stesso errore si verifica anche quando la parola chiave UPPER o LOWER non viene utilizzata in entrambi i punti nell'espressione selezionata e raggruppa per espressione.

Sbagliato :-

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

Giusto :-

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

1

Il gruppo di viene utilizzato per aggregare alcuni dati, a seconda della funzione di aggregazione, oltre a ciò è necessario inserire colonne o colonne in cui è necessario il raggruppamento.

per esempio:

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

Ciò comporterà lo stipendio massimo dei dipartimenti.

Ora se omettiamo la d.deptnoclausola from group by, si otterrà lo stesso errore.


1

Oltre alle altre risposte, questo errore può verificarsi in caso di incoerenza nella clausola order by. Per esempio:

select 
    substr(year_month, 1, 4)
    ,count(*) as tot
from
    schema.tbl
group by
    substr(year_month, 1, 4)
order by
    year_month
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.