ORA-00979 nie jest grupą według wyrażenia

147

Otrzymuję ORA-00979 z następującym zapytaniem:

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;

Nie mogłem znaleźć żadnych przykładów, które miałyby klauzule GROUP BY i ORDER BY w tym samym zapytaniu. Próbowałem usunąć każde pole z grupy pojedynczo, ale nadal pojawia się ten sam błąd.

Theresa
źródło

Odpowiedzi:

232

Musisz umieścić wszystkie Kolumny SELECTw GROUP BYlub używać funkcji na nich, które skompresować wyniki do pojedynczej wartości (jak MIN, MAXlubSUM ).

Prosty przykład, aby zrozumieć, dlaczego tak się dzieje: Wyobraź sobie, że masz taką bazę danych:

FOO BAR
0   A
0   B

i uciekasz SELECT * FROM table GROUP BY foo. Oznacza to, że baza danych musi zwrócić pojedynczy wiersz jako wynik z pierwszą kolumną, 0aby spełnić warunek, GROUP BYale są teraz dwie wartości bardo wyboru. Jakiego wyniku byś się spodziewał - Alub B? A może baza danych powinna zwrócić więcej niż jeden wiersz, naruszając kontrakt GROUP BY?

Aaron Digulla
źródło
7
Nie, nie musisz składać ich w swoim zamówieniu według klauzuli
Xaisoft
3
Próbowałem dodać dwie kolumny z ORDER BY do GROUP BY. To się udało. Dzięki!
Theresa
1
Albo inaczej: jeśli masz dwie kolumny i grupujesz je według pierwszej, oznacza to, że będziesz mieć kilka wartości z drugiej kolumny na wiersz wynikowy. Ponieważ istnieje tylko jeden wiersz wyników, ale wiele wartości do wyboru, którą z nich powinna zwrócić baza danych? Pierwszy, na który się natknie?
Aaron Digulla
6
@AaronDigulla To właśnie robi MySQL, a świat się nie skończył: p
Chris Baker
1
Częściowo się zgadzam. Ale załóżmy następujący przypadek: istnieją 4 kolumny: A, B, C i D. Teraz ustawiłem (A, B, C) jako klucz złożony. Wtedy „wybierz A, B, max (C), D ... grupuj według A, B” nie jest dwuznaczne, ponieważ dla każdej kombinacji A, B i C, D jest już zdefiniowane. Wciąż wyrocznia odmawia wykonania swojej pracy.
środa,
17

Uwzględnij w GROUP BYklauzuli wszystkie SELECTwyrażenia, które nie są argumentami funkcji grupy.

Xaisoft
źródło
9

Szkoda, że ​​Oracle ma takie ograniczenia. Jasne, wynik dla kolumny, której nie ma w GROUP BY byłby losowy, ale czasami tego chcesz. Głupia Oracle, możesz to zrobić w MySQL / MSSQL.

ALE istnieje obejście dla Oracle:

Chociaż poniższa linia nie działa

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

Możesz oszukać Oracle za pomocą kilku 0, takich jak poniżej, aby utrzymać kolumnę w zakresie, ale nie grupować według niej (zakładając, że są to liczby, w przeciwnym razie użyj 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
źródło
@GlennFromIowa biorąc pod uwagę, że moja pseudo tabela nie jest zdefiniowana powyżej rygorystycznie i że nie pracuję już dla firmy z 11g, nie mogę podać lepszego przykładu, chociaż był to problem, kiedy ostatnio go testowałem.
Joseph Lust
4
Z ciekawości, jaki jest przykład, kiedy chciałbyś otrzymać losowy wynik? Nie przychodzi mi do głowy żaden powód, dla którego chciałbyś pogrupować według FOO i otrzymać losowy wiersz dla BAR.
Kyle Bridenstine
4

Jeśli nie grupowania dzięki tym GROUP BYklauzulę, każdy wyraz w SELECT, co nie jest funkcja grupa (lub funkcja kruszywa lub zagregowane kolumna), takie jak COUNT, AVG, MIN, MAX, SUMi tak dalej ( Lista funkcji agregujących ) powinny być obecne wGROUP BY klauzuli.

Przykład (poprawny sposób) (tutaj employee_idnie jest funkcja grupowa (kolumna niezagregowana), więc musi się pojawić w GROUP BY. Z kolei suma (wynagrodzenie) jest funkcją grupową (kolumna zagregowana), więc nie jest wymagane, aby występowała w GROUP BYklauzuli .

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

Przykład (błędny sposób) (tutaj employee_idnie jest funkcja grupowa i nie pojawia się w GROUP BYklauzuli, co doprowadzi do błędu ORA-00979.

   SELECT employee_id, sum(salary) 
   FROM employees;

Aby poprawić, musisz wykonać jedną z następujących czynności:

  • Uwzględnij wszystkie niezagregowane wyrażenia wymienione w SELECTklauzuli w GROUP BY klauzuli
  • Usuń funkcję grupy (agregującą) z SELECTklauzuli.
fg78nc
źródło
2

Należy wykonać następujące czynności:

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
źródło
1

Ten sam błąd pojawia się również, gdy UPPER lub LOWER słowo kluczowe nie jest używane zarówno w miejscu w wyrażeniu zaznaczania, jak iw grupie według wyrażenia.

Źle :-

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

Dobrze :-

select UPPER(a) , count(*) from my_table group by UPPER(a) .
Opster Elasticsearch Pro-Vijay
źródło
1

Grupuj według służy do agregowania niektórych danych, w zależności od funkcji agregującej, i poza tym, że musisz umieścić kolumnę lub kolumny, do których potrzebujesz grupowania.

na przykład:

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

Zaowocuje to maksymalnym wynagrodzeniem działów.

Teraz, jeśli pominiemy d.deptnoklauzulę from group by, wystąpi ten sam błąd.

Muhammad Nadeem
źródło
1

Oprócz innych odpowiedzi ten błąd może wystąpić, jeśli występuje niespójność w kolejności w klauzuli. Na przykład:

select 
    substr(year_month, 1, 4)
    ,count(*) as tot
from
    schema.tbl
group by
    substr(year_month, 1, 4)
order by
    year_month
3pitt
źródło