ORA-00979 no es un grupo por expresión

147

Estoy obteniendo ORA-00979 con la siguiente 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;

No pude encontrar ningún ejemplo que tuviera cláusulas GROUP BY y ORDER BY en la misma consulta. Intenté eliminar cada campo del grupo de a uno por vez, pero sigo recibiendo el mismo error.

Hay una
fuente

Respuestas:

232

Debe colocar todas las columnas de SELECTen el GROUP BYo utilizar funciones en ellos que comprimen los resultados a un solo valor (como MIN, MAXo SUM).

Un ejemplo simple para entender por qué sucede esto: imagine que tiene una base de datos como esta:

FOO BAR
0   A
0   B

y se ejecuta SELECT * FROM table GROUP BY foo. Esto significa que la base de datos debe devolver una sola fila como resultado con la primera columna 0para cumplir con el, GROUP BYpero ahora hay dos valores barpara elegir. ¿Qué resultado esperarías, Ao B? ¿O debería la base de datos devolver más de una fila, violando el contrato de GROUP BY?

Aaron Digulla
fuente
77
No, no necesita ponerlos en su orden por cláusula
Xaisoft el
3
Intenté agregar las dos columnas en ORDER BY al GROUP BY. Eso funciono. ¡Gracias!
Theresa
1
O para decirlo de otra manera: si tiene dos columnas y agrupa por la primera, eso significa que tendrá varios valores de la segunda columna por fila de resultados. Dado que solo hay una única fila de resultados pero muchos valores para elegir, ¿cuál debería devolver la base de datos? ¿El primero con el que tropieza?
Aaron Digulla
66
@AaronDigulla Eso es lo que hace MySQL, y el mundo no terminó: p
Chris Baker
1
Estoy parcialmente de acuerdo Pero suponga el siguiente caso: hay 4 columnas: A, B, C y D. Ahora configuro (A, B, C) como una clave compuesta. Entonces "seleccionar A, B, max (C), D ... agrupar por A, B" no es ambiguo, ya que para cada combinación de A, B y C, D ya está definido. Aún así, Oracle se niega a hacer su trabajo.
ga
17

Incluya en la GROUP BYcláusula todas las SELECTexpresiones que no sean argumentos de función de grupo.

Xaisoft
fuente
9

Lástima que Oracle tenga limitaciones como estas. Claro, el resultado para una columna que no está en GROUP BY sería aleatorio, pero a veces quieres eso. Oracle tonto, puedes hacer esto en MySQL / MSSQL.

PERO hay una solución para Oracle:

Si bien la siguiente línea no funciona

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

Puede engañar a Oracle con algunos ceros como el siguiente, para mantener su columna dentro del alcance, pero no agruparla (suponiendo que se trata de números, de lo contrario 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
fuente
@GlennFromIowa dado que mi pseudo tabla no está rigurosamente definida anteriormente, y que ya no trabajo para una empresa con 11 g, no puedo proporcionar un mejor ejemplo, aunque fue un problema la última vez que lo probé.
Joseph Lust
44
Solo por curiosidad, ¿cuál es un ejemplo de cuándo quieres un resultado aleatorio? No se me ocurre ninguna razón por la que desee agrupar por FOO y obtener una fila aleatoria para BAR.
Kyle Bridenstine
4

Si la agrupación en virtud de la inclusión de GROUP BYla cláusula, cualquier expresión en SELECT, que no es función de grupo (o función de agregado o columna agregada), tales como COUNT, AVG, MIN, MAX, SUMy así sucesivamente ( Lista de funciones de agregación ) debe estar presente en GROUP BYcláusula.

Ejemplo (forma correcta) (aquí employee_idno es una función de grupo (columna no agregada), por lo que debe aparecer en GROUP BY. Por el contrario, sum (salario) es una función de grupo (columna agregada), por lo que no es necesario que aparezca en la GROUP BYcláusula .

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

Ejemplo (forma incorrecta) (aquí employee_idno hay función de grupo y no aparece en la GROUP BYcláusula, lo que conducirá al error ORA-00979.

   SELECT employee_id, sum(salary) 
   FROM employees;

Para corregir necesita hacer uno de los siguientes:

  • Incluya todas las expresiones no agregadas enumeradas en la SELECTcláusula en la GROUP BYcláusula
  • Eliminar la función de grupo (agregado) de la SELECTcláusula.
fg78nc
fuente
2

Debes hacer lo siguiente:

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

El mismo error también se produce cuando la palabra clave SUPERIOR o INFERIOR no se usa en ambos lugares en la expresión de selección y en el grupo por expresión.

Incorrecto :-

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

Derecho :-

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

El grupo by se usa para agregar algunos datos, dependiendo de la función de agregado, y aparte de eso, debe colocar la columna o columnas en las que necesita la agrupación.

por ejemplo:

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

Esto dará como resultado el salario máximo del departamento.

Ahora, si omitimos la d.deptnocláusula from group by, dará el mismo error.

Muhammad Nadeem
fuente
1

Además de las otras respuestas, este error puede resultar si hay una inconsistencia en un orden por cláusula. Por ejemplo:

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