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.

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?


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.


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);

@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.

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;

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) .

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.


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.