ORA-00979 не група за виразом


147

Я отримую ORA-00979 із таким запитом:

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;

Я не зміг знайти жодного прикладу, у якому в одному запиті були і пропозиції GROUP BY, і ORDER BY. Я намагався видалити кожне поле з групи по одному, але все одно отримую ту саму помилку.

Відповіді:


232

Ви повинні помістити всі стовпці SELECTв GROUP BYабо використовувати функції, які стискають результати до одного значення (наприклад MIN, MAXабо SUM).

Простий приклад, щоб зрозуміти, чому це відбувається: Уявіть, у вас є така база даних:

FOO BAR
0   A
0   B

і ти біжиш SELECT * FROM table GROUP BY foo. Це означає, що база даних повинна повернути один рядок у результаті, з першим стовпцем 0для виконання, GROUP BYале тепер є два значення barдля вибору. Якого результату ви б очікували - Aчи B? Або база даних повинна повертати більше, ніж один рядок, порушуючи договір GROUP BY?


7
Ні, вам не потрібно ставити їх у свій порядок за допомогою пункту
Xaisoft

3
Я спробував додати два стовпчики ORDER BY до GROUP BY. Це спрацювало. Дякую!
Тереза

1
Або кажучи інакше: якщо у вас є два стовпчики та згрупуються по першому, це означає, що у другому стовпчику у ряді результатів буде кілька значень. Оскільки є лише один рядок результатів, але багато значень для вибору, яке з них повинен повертати БД? Перше на що натрапляє?
Аарон Дігулла

6
@AaronDigulla Ось що робить MySQL, і світ не закінчився: p
Chris Baker

1
Я частково згоден. Але припустимо такий випадок: є 4 стовпчики: A, B, C і D. Тепер я встановив (A, B, C) як складений ключ. Тоді "вибір A, B, max (C), D ... групи за A, B" не є неоднозначним, оскільки для кожної комбінації A, B і C, D вже визначено. Досі Oracle відмовляється виконувати свою справу.
га

17

Додайте до GROUP BYпункту всі SELECTвирази, які не є аргументами групової функції.


9

Шкода, що Oracle має такі обмеження. Звичайно, результат для стовпця, який не знаходиться у групі BY, був би випадковим, але іноді ви цього хочете. Дурний Oracle, ви можете це зробити в MySQL / MSSQL.

АЛЕ існує робота над Oracle:

Поки наступний рядок не працює

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

Ви можете обдурити Oracle за допомогою таких значень 0, як наступний, щоб зберегти колонку в обсязі, але не групувати її (якщо це цифри, інакше використовуйте 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, зважаючи на те, що моя псевдо таблиця не є чітко визначеною вище, і що я більше не працюю для фірми з 11g, я не можу надати кращого прикладу, хоча це було проблемою, коли я востаннє тестував її.
Йосип Похоть

4
Щойно з цікавості є прикладом, коли ви хочете отримати випадковий результат? Я не можу придумати жодної причини, яку б ви хотіли згрупувати за FOO і отримати випадковий рядок для BAR.
Кайл Бріденстін

4

Якщо угруповання в силу в тому числі GROUP BYпункт, будь-який вираз SELECT, яке не є функцією групи (або агрегатної функції або агрегованих колонки) , такі як COUNT, AVG, MIN, MAX, SUMі так далі ( список агрегатних функцій ) повинні бути присутніми в GROUP BYстатті.

Приклад (правильний спосіб) (тут employee_idце не групова функція (неагрегований стовпець), тому вона повинна відображатися GROUP BY. На відміну від цього, сума (зарплата) - це групова функція (агрегований стовпець), тому в GROUP BYпункті не потрібно з’являтись .

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

Приклад (неправильний спосіб) (тут employee_idце не групова функція, і вона не відображається в GROUP BYпункті, що призведе до помилки ORA-00979

   SELECT employee_id, sum(salary) 
   FROM employees;

Для виправлення потрібно зробити одне з наступних дій:

  • Включіть усі зведені вирази, перелічені в SELECTпункті, у GROUP BYпункті
  • Вилучити функцію групи (сукупності) із SELECTпункту.

2

Ви повинні зробити наступне:

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

Ця ж помилка також виникає, коли ключове слово UPPER або LOWER не використовується в обох місцях у виділеному виразі та групі за виразом.

Неправильно: -

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

Право: -

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

1

Група by використовується для агрегації деяких даних, залежно від функції сукупності, а крім того, вам потрібно поставити стовпчик або стовпці, до яких вам потрібне групування.

наприклад:

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

Це призведе до того, що відомства отримають максимальну зарплату.

Тепер, якщо ми пропустимо d.deptnoгрупу із пункту, вона призведе до тієї ж помилки.


1

Окрім інших відповідей, ця помилка може спричинитись, якщо в наказі за пунктом є невідповідність. Наприклад:

select 
    substr(year_month, 1, 4)
    ,count(*) as tot
from
    schema.tbl
group by
    substr(year_month, 1, 4)
order by
    year_month
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.