Pourquoi une «fonction de groupe non unique» est-elle autorisée dans une sous-sélection mais pas seule?

9

Pourquoi la première requête n'échoue-t-elle pas avec la même erreur que la seconde:

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:
*/

modifier: informations de version ajoutées:

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                 
*/

modifier: paramètres non par défaut ajoutés:

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 dit d'essayer topanswers.xyz
la source
Pouvez-vous reproduire cela sur un petit ensemble de données sur SQL Fiddle?
Philᵀᴹ
Je suppose que c'est un bogue dans l'analyseur / optimiseur Oracle11 (il est probablement trop intelligent et ignore product_iden mode en ligne). Les deux échouent dans Oracle10g ("pas une fonction de groupe mono-groupe").
a1ex07
@Jack À quel niveau de patch êtes-vous?
Philᵀᴹ
@Phil SQLFiddle donne le même résultat étrange (c'est 11.2.0.2 XE, je suis sur 11.2.0.3 SE 64bit Linux)
Jack dit d'essayer topanswers.xyz
@ a1ex07 Je suis sûr que vous avez raison, c'est un bug d'optimiseur: select sum(units), avg(product_id) from (select product_id, sum(units) units from w);échoue comme prévu.
Jack dit d'essayer topanswers.xyz le

Réponses:

3

Je dirais que c'est un bug dans votre version Oracle.

  • Dans 11.1.0.7.0, 9.2.0.7.0et 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 sous-requête n'est certainement pas valide. L'optimiseur peut simplifier la fusion des deux requêtes agrégées (comme suggéré par @ a1ex07 ), mais la fusion ne doit en aucun cas avoir lieu car la requête n'est pas logiquement correcte.

Il y a plusieurs bugs concernant un GROUP BYcomportement incorrect enregistré dans MOS, mais je n'ai pas pu en trouver un qui ressemble exactement à celui-ci. Le plus proche que j'ai trouvé est le bogue 8945974 où une requête incorrecte avec un GROUP BYfonctionnait 10.2.0.3et corrigeait la base de données pour la 10.2.0.4faire échouer de manière appropriée.

Vincent Malgrat
la source
Votre Linux 11.2 64 bits est-il comme le mien?
Jack dit d'essayer topanswers.xyz le
Oui, il s'agit du site Web de démonstration d' apex.oracle.com . Exactement la même v$versioninfo!
Vincent Malgrat
Très étrange. Y a-t-il des différences importantes avec moi select name, value from v$parameter where isdefault = 'FALSE' order by name;?
Jack dit d'essayer topanswers.xyz le
Malheureusement, je n'ai pas accès à cette vue sur cette instance.
Vincent Malgrat
entre les astuces no_mergeet materializene font aucune différence. Je pense que techniquement, cela élimine la colonne inutilisée plutôt que de fusionner les requêtes, mais je suppose que le bogue est qu'il ne génère pas d'abord une erreur d'analyse.
Jack dit d'essayer topanswers.xyz le
1

Je soupçonne que l'optimiseur de requêtes applique une transformation à votre première requête qui élimine product_id de la vue en ligne, puis fusionne la vue en ligne dans la requête principale pour qu'elle s'exécute en tant que:

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

En fait, il le transforme probablement ensuite en:

select sum(units) from (select 10 units from dual union all select 5 from dual);
David Aldridge
la source
Vos deux exemples partagent le même plan (voir ici et ici ) mais mon original a un plan différent , et l'utilisation de no_mergeou materializene fait aucune différence, c'est pourquoi je pense que le CBO élimine product_id de la vue en ligne mais ne fusionne pas le vue en ligne dans la requête principale.
Jack dit d'essayer topanswers.xyz le