¿Por qué se permite una "función de grupo que no sea de un solo grupo" en una subselección pero no por sí sola?

9

¿Por qué la primera consulta no falla con el mismo error que la segunda?

with w as (select 1 product_id, 10 units from dual union all select 2, 5 from dual)
select sum(units) from (select product_id, sum(units) units from w);

/*
SUM(UNITS)
----------
        15 
*/

with w as (select 1 product_id, 10 units from dual union all select 2, 5 from dual)
select product_id, sum(units) units from w;

/*
Error starting at line 7 in command:
with w as (select 1 product_id, 10 units from dual union all select 2, 5 from dual)
select product_id, sum(units) units from w
Error at Command Line:8 Column:8
Error report:
SQL Error: ORA-00937: not a single-group group function
00937. 00000 -  "not a single-group group function"
*Cause:    
*Action:
*/

editar: información de versión agregada:

select * from v$version;
/*
BANNER                                                                         
--------------------------------------------------------------------------------
Oracle Database 11g Release 11.2.0.3.0 - 64bit Production                        
PL/SQL Release 11.2.0.3.0 - Production                                           
CORE    11.2.0.3.0  Production                                                         
TNS for Linux: Version 11.2.0.3.0 - Production                                   
NLSRTL Version 11.2.0.3.0 - Production                 
*/

editar: parámetros no predeterminados agregados:

select name, value from v$parameter where isdefault = 'FALSE' order by name;
/*
NAME                              VALUE                                                                                                                             
--------------------------------- ----------------------------------------------------------------------------------------------------------------------------------
aq_tm_processes                   1                                                                                                                                 
archive_lag_target                3600                                                                                                                              
audit_file_dest                   /u01/app/oracle/admin/oracle/adump                                                                                                
audit_trail                       NONE                                                                                                                              
compatible                        11.2.0.3                                                                                                                          
control_file_record_keep_time     31                                                                                                                                
control_files                     /home/oracle/cfile/controlfile.dat, +DATA/oracle/controlfile/current.915.730988607, +FRA/oracle/controlfile/current.970.730988607 
core_dump_dest                    /u01/app/oracle/admin/oracle/cdump                                                                                                
db_block_size                     4096                                                                                                                              
db_create_file_dest               +DATA                                                                                                                             
db_domain                                                                                                                                                           
db_file_multiblock_read_count     1                                                                                                                                 
db_name                           oracle                                                                                                                            
db_recovery_file_dest             +FRA                                                                                                                              
db_recovery_file_dest_size        375809638400                                                                                                                      
diagnostic_dest                   /u01/app/oracle                                                                                                                   
dispatchers                       (PROTOCOL=TCP) (SERVICE=oracleXDB)                                                                                                
event                                                                                                                                                               
filesystemio_options              setall                                                                                                                            
global_names                      TRUE                                                                                                                              
job_queue_processes               10                                                                                                                                
log_archive_dest_1                                                                                                                                                  
log_archive_dest_10               LOCATION=USE_DB_RECOVERY_FILE_DEST MANDATORY REOPEN=60                                                                            
log_checkpoint_timeout            30                                                                                                                                
memory_max_target                 36507222016                                                                                                                       
memory_target                     36507222016                                                                                                                       
nls_language                      ENGLISH                                                                                                                           
nls_length_semantics              BYTE                                                                                                                              
nls_territory                     UNITED KINGDOM                                                                                                                    
open_cursors                      300                                                                                                                               
pga_aggregate_target              0                                                                                                                                 
processes                         150                                                                                                                               
remote_login_passwordfile         EXCLUSIVE                                                                                                                         
sga_max_size                      32212254720                                                                                                                       
sga_target                        0                                                                                                                                 
shared_pool_size                  536870912                                                                                                                         
smtp_out_server                   mailout.redacted.com                                                                                                                   
streams_pool_size                 1073741824                                                                                                                        
undo_management                   AUTO                                                                                                                              
undo_retention                    900                                                                                                                               
undo_tablespace                   TS_UNDO                                                                                                                           

 41 rows selected
*/
Jack dice que intente topanswers.xyz
fuente
¿Puedes reproducir esto en un pequeño conjunto de datos en sql fiddle?
Philᵀᴹ
Supongo que es un error en el analizador / optimizador Oracle11 (probablemente es demasiado inteligente e ignora product_iden la vista en línea). Ambos fallan en Oracle10g ("no es una función de grupo de un solo grupo").
a1ex07
@ Jack ¿En qué nivel de parche estás?
Philᵀᴹ
@Phil SQLFiddle da el mismo resultado extraño (es 11.2.0.2 XE, estoy en 11.2.0.3 SE 64bit Linux)
Jack dice que intente topanswers.xyz
@ a1ex07 Estoy seguro de que tiene razón, es un error del optimizador: select sum(units), avg(product_id) from (select product_id, sum(units) units from w);falla como se esperaba.
Jack dice que intente topanswers.xyz

Respuestas:

3

Yo diría que es un error en su versión de Oracle.

  • En 11.1.0.7.0, 9.2.0.7.0y 11.2.0.3.0:

    SQL> with w as (
      2  SELECT 1 product_id, 10 units FROM dual
      3  UNION ALL
      4  SELECT 2, 5 FROM dual)
      5  SELECT SUM(units) FROM (SELECT product_id, SUM(units) units FROM w);
    
    ORA-00937: not a single-group group function

La subconsulta definitivamente no es válida. Puede haber una simplificación realizada por el optimizador al fusionar las dos consultas agregadas (como lo sugiere @ a1ex07 ), pero la fusión no debería tener lugar en ningún caso ya que la consulta no es lógicamente correcta.

Hay varios errores relacionados con el GROUP BYcomportamiento incorrecto registrado en MOS, pero no pude encontrar uno que se vea exactamente como este. El más cercano que encontré es el error 8945974, donde una consulta incorrecta con un GROUP BYestaba trabajando 10.2.0.3y parcheando la base de datos para 10.2.0.4que fallara adecuadamente.

Vincent Malgrat
fuente
¿Es su Linux 11.2 de 64 bits como el mío?
Jack dice que intente topanswers.xyz
Sí, es del sitio web de demostración apex.oracle.com . ¡Exactamente la misma v$versioninformación!
Vincent Malgrat
Muy raro. ¿Alguna diferencia significativa con mi select name, value from v$parameter where isdefault = 'FALSE' order by name;?
Jack dice que intente topanswers.xyz
Lamentablemente no tengo acceso a esta vista en esa instancia.
Vincent Malgrat
Por cierto, las pistas no_mergey materializeno hacen ninguna diferencia. Creo que técnicamente está eliminando la columna no utilizada en lugar de fusionar las consultas, pero supongo que el error es que no arroja primero un error de análisis.
Jack dice que intente topanswers.xyz
1

Sospecho que el optimizador de consultas está aplicando una transformación a su primera consulta que elimina product_id de la vista en línea, luego combina la vista en línea en la consulta principal para que se ejecute como:

with w as (select 1 product_id, 10 units from dual union all select 2, 5 from dual)
select sum(units) from w;

En realidad, probablemente lo transforma aún más a:

select sum(units) from (select 10 units from dual union all select 5 from dual);
David Aldridge
fuente
Sus dos ejemplos comparten el mismo plan (vea aquí y aquí ) pero mi original tiene un plan diferente , y usar no_mergeo materializeno hace ninguna diferencia, por eso creo que la CBO está eliminando product_id de la vista en línea pero no fusionando el vista en línea en la consulta principal.
Jack dice que intente topanswers.xyz