ORA-00979 não é um grupo por expressão

147

Estou recebendo o ORA-00979 com a seguinte consulta:

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;

Não consegui encontrar nenhum exemplo que tivesse as cláusulas GROUP BY e ORDER BY na mesma consulta. Tentei remover cada campo do grupo um por vez, mas ainda estou recebendo o mesmo erro.

Há um
fonte

Respostas:

232

Você deve colocar todas as colunas do SELECTno GROUP BYou utilizar as funções neles que comprimem os resultados para um único valor (como MIN, MAXou SUM).

Um exemplo simples para entender por que isso acontece: imagine que você tenha um banco de dados como este:

FOO BAR
0   A
0   B

e você corre SELECT * FROM table GROUP BY foo. Isso significa que o banco de dados deve retornar uma única linha como resultado com a primeira coluna 0para atender a, GROUP BYmas agora existem dois valores barpara escolher. Qual resultado você esperaria - Aou B? Ou o banco de dados deve retornar mais de uma linha, violando o contrato de GROUP BY?

Aaron Digulla
fonte
7
Não, você não precisa colocá-los em sua ordem por cláusula
Xaisoft
3
Tentei adicionar as duas colunas no ORDER BY ao GROUP BY. Isso funcionou. Obrigado!
Theresa
1
Ou, de outra forma: se você tem duas colunas e agrupa pela primeira, significa que você terá vários valores da segunda coluna por linha de resultado. Como existe apenas uma linha de resultado, mas muitos valores para escolher, qual o DB deve retornar? O primeiro tropeça?
23416 Aaron Digulla
6
@AaronDigulla Isso é o que o MySQL faz e o mundo não acabou: p
Chris Baker
1
Eu concordo parcialmente. Mas assuma o seguinte caso: existem 4 colunas: A, B, C e D. Agora eu defino (A, B, C) como uma chave composta. Então "selecione A, B, max (C), D ... agrupe por A, B" não é ambíguo, pois para cada combinação de A, B e C, D já está definido. Ainda, a Oracle se recusa a fazer seu trabalho.
ga
17

Inclua na GROUP BYcláusula todas as SELECTexpressões que não são argumentos de função de grupo.

Xaisoft
fonte
9

Pena que o Oracle tenha limitações como estas. Claro, o resultado para uma coluna que não esteja no GROUP BY seria aleatório, mas às vezes você deseja isso. Oracle bobo, você pode fazer isso no MySQL / MSSQL.

MAS existe uma solução alternativa para o Oracle:

Embora a seguinte linha não funcione

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

Você pode enganar o Oracle com alguns 0s como o seguinte, para manter sua coluna no escopo, mas não agrupá-la (assumindo que sejam números, caso contrário, use 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
fonte
@GlennFromIowa, considerando que minha pseudo tabela não está rigorosamente definida acima e que não trabalho mais para uma empresa com 11g, não posso fornecer um exemplo melhor, embora tenha sido um problema quando a testei pela última vez.
Joseph Lust
4
Apenas por curiosidade, como é um exemplo de quando você deseja um resultado aleatório? Não consigo pensar em nenhum motivo pelo qual você queira agrupar por FOO e obter uma linha aleatória para BAR.
Kyle Bridenstine
4

Se você agrupar em virtude da inclusão de GROUP BYcláusula, qualquer expressão no SELECT, que não é função de grupo (ou função de agregação ou coluna agregada), tais como COUNT, AVG, MIN, MAX, SUMe assim por diante ( Lista de funções de agregação ) deve estar presente na GROUP BYcláusula.

Exemplo (maneira correta) (aqui employee_idnão é função de grupo (coluna não agregada), portanto, ela deve aparecer GROUP BY. Por outro lado, soma (salário) é uma função de grupo (coluna agregada), portanto, não é necessário que apareça na GROUP BYcláusula .

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

Exemplo (maneira incorreta) (aqui employee_idnão é função de grupo e não aparece na GROUP BYcláusula, que levará ao erro ORA-00979.

   SELECT employee_id, sum(salary) 
   FROM employees;

Para corrigir, você deve executar um dos seguintes procedimentos:

  • Inclua todas as expressões não agregadas listadas na SELECTcláusula na GROUP BYcláusula
  • Remova a função de grupo (agregada) da SELECTcláusula
fg78nc
fonte
2

Você deve fazer o seguinte:

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
fonte
1

O mesmo erro também ocorre quando a palavra-chave UPPER ou LOWER não é usada em ambos os lugares na expressão selecionada e agrupada por expressão.

Errado: -

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

Certo :-

select UPPER(a) , count(*) from my_table group by UPPER(a) .
Opster Elasticsearch Pro-Vijay
fonte
1

O grupo by é usado para agregar alguns dados, dependendo da função agregada, e outros que você precisa colocar coluna ou colunas nas quais você precisa do agrupamento.

por exemplo:

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

Isso resultará no salário máximo dos departamentos.

Agora, se omitirmos a d.deptnocláusula from group by, ocorrerá o mesmo erro.

Muhammad Nadeem
fonte
1

Além das outras respostas, esse erro pode ocorrer se houver uma inconsistência em uma cláusula order by. Por exemplo:

select 
    substr(year_month, 1, 4)
    ,count(*) as tot
from
    schema.tbl
group by
    substr(year_month, 1, 4)
order by
    year_month
3pitt
fonte