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