Я получаю 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 в том же запросе. Я попытался удалить каждое поле из группы по одному, но все равно получаю ту же ошибку.
Вы должны поместить все столбцы 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
?
Включить в предложение GROUP BY
все выражения SELECT
, которые не являются аргументами групповой функции.
Слишком плохо Oracle имеет такие ограничения. Конечно, результат для столбца, не входящего в GROUP 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);
Группа by используется для агрегирования некоторых данных, в зависимости от агрегатной функции, и кроме нее вам нужно поместить столбец или столбцы, которым нужна группировка.
например:
select d.deptno, max(e.sal)
from emp e, dept d
where e.deptno = d.deptno
group by d.deptno;
Это приведет к максимальной заработной плате отделов.
Теперь, если мы опустим предложение d.deptno из group by, оно даст ту же ошибку.
Если вы выполняете поиск в соответствии с предложением 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
.Такая же ошибка возникает, когда ключевое слово ВЕРХНИЕ или НИЖНИЕ не используется в обоих местах в выражении выбора и группе по выражению.
Неверно: -
select a , count(*) from my_table group by UPPER(a) .
Вправо: -
select UPPER(a) , count(*) from my_table group by UPPER(a) .
Вы должны сделать следующее:
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;