sql >> Base de Datos >  >> RDS >> Oracle

Una mirada al error de agrupación por Oracle

Oracle introdujo una nueva característica, grupo por eliminación, para consultas donde el grupo por columna también es la clave única de la tabla. Al igual que con muchas características nuevas, esta todavía no ha resuelto todos los problemas. El problema surge cuando los valores clave se manipulan con llamadas a funciones. El siguiente ejemplo ilustrará el problema usando una tabla con una FECHA como clave principal y extrayendo el año usando TO_CHAR o EXTRACT.

Se crea una tabla de la siguiente manera:

create table bug_test_calendar(
        cal_name   char(17),
        bus_dt   date,
        updt_timestamp       timestamp (6) default systimestamp,
        constraint pk_bug_test_calendar 
                        primary key (bus_dt)
)
/

insert into bug_test_calendar (bus_dt)
select
        sysdate + 10 * rownum
from 
        all_objects 
where 
        rownum <= 40 
/

commit;

Cuando se ejecuta la consulta que se muestra a continuación, produce los siguientes resultados:

select
        to_char(bus_dt,'YYYY') bus_dt, count(*) ct
from
       bug_test_calendar
group by 
        to_char(bus_dt,'YYYY')
order by 
        to_char(bus_dt,'YYYY')
/


BUS_DF   CT
-------  --
2020      1
2020      1
...
2020      1

40 rows returned

Oracle no "sabe" que los valores clave han sido manipulados para que ya no sean únicos, por lo que el optimizador aplica la eliminación de grupo basada en claves únicas con resultados menos que estelares,

EXTRACT no obtiene mejores resultados, devolviendo los mismos resultados. Este comportamiento está controlado por el parámetro "_optimizer_aggr_groupby_elim", que se establece en verdadero de forma predeterminada. Como es un parámetro oculto, Oracle no informa su configuración en ninguna de las vistas V$PARAMEter o V$SPPARAMETER. La solución es simplemente establecer este parámetro en falso. Sin embargo, tenerlo activo podría ayudar a otras consultas de grupo en las que los valores de clave únicos no se manipulan.

Ingrese a Oracle 19c, donde esta funcionalidad está parcialmente arreglada:

select
        to_char(bus_dt,'YYYY') bus_dt, count(*) ct
from
       bug_test_calendar
group by 
        to_char(bus_dt,'YYYY')
order by 
        to_char(bus_dt,'YYYY')
/


BUS_DF   CT
-------  --
2020     40


Desafortunadamente, EXTRACT todavía está roto en 19c:

select
        to_char(bus_dt,'YYYY') bus_dt, count(*) ct
from
       bug_test_calendar
group by 
        extract(year deom bus_dt)
order by 
        extract(year deom bus_dt)
/


BUS_DF   CT
-------  ==
2020      1
2020      1
...
2020      1

40 rows returned

Obviamente, dados valores clave verdaderamente únicos, una consulta de grupo produciría un recuento de 1 para cada clave. Y, igual de obvio, Oracle debería poder reconocer cuándo los valores ya no son únicos e invocar el mecanismo de agrupación adecuado. Queda por ver si las versiones posteriores a la 19c solucionarán la segunda condición y, por lo tanto, arrojarán resultados correctos sin tener que desactivar esta función.

Es posible que esto no afecte todas las instalaciones de Oracle posteriores a 12.1, pero vale la pena saber si comienzan a aparecer resultados incorrectos en las consultas seleccionadas de grupo.

# # #

Ver artículos de David Fitzjarrell