2014-12-05 18 views
9

Sono in esecuzione sotto la query su Oracle Exadata.Risultato Oracle senza gruppo di

Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - produzione 64bit Con la divisione, Real Application Clusters, Storage Management automatica, OLAP, Data Mining e Real Application Testing opzioni

select sum (t.sum_edw_trx_cnt) 
    from ( 
     select max(x.edw_trx_cnt)sum_edw_trx_cnt, 
       x.prctr_cell_nbr 
      from p_prctr_smpl_pf_sp3 x 
      where mdld_prctr_flg = 'Y' 
     )t; 

Mi aspettavo che Oracle restituisse un errore poiché - Come potete vedere, non c'è una clausola group by nella query interna "t" e mi aspettavo che questa query fallisse.

Ci sono milioni di record e per ogni prctr_cell_nbr voglio il conteggio massimo e quindi la query esterna dovrebbe sommare i conteggi massimi per ogni prctr_cell. È una query semplice. Tuttavia, la query viene eseguita e restituisce l'output di 112 che è il conteggio massimo dalla query interna.

Sono perplesso da questo comportamento poiché questo non è il risultato corretto restituito dalla query. Non penso che questo sia un comportamento noto, qualcuno lo ha visto recentemente?

Grazie

+0

Tuttavia si ottiene un errore se si esegue semplicemente la selezione interna corretta? – xQbert

+0

Sì. La query interna risulta in errore se eseguita separatamente. –

+0

http://dba.stackexchange.com/questions/39674/why-is-a-non-single-group-funzional-funzionamento-in-un-subselect-but-not-on-it – Multisync

risposta

0

Non credo che i risultati potrebbero essere corretto se si esclude clausola group by. Il risultato per query esterna sarebbe corretto solo quando la query interna produce il record singolo che è uguale all'esclusione di gruppo per colonna.

 
-- No group by clasue and Oracle silently ignores group by in 
-- inner query and retrns the max numbre. See output showing count = 1 

select sum (t.sum_edw_trx_cnt) ,count(1) from (
select max(x.edw_trx_cnt)sum_edw_trx_cnt, x.prctr_cell_nbr 
from p_prctr_smpl_pf_sp3 x 
where x.mdld_prctr_flg = 'Y' 
)t; 

SUM(T.SUM_EDW_TRX_CNT) COUNT(1) 
---------------------------------- 
112      1 
` 

-- Here is the query with group by clause 
-- The number of cells are indicated by count and the sum of edw_trx_cnt is 
-- 19838749 as expected. 
`  
select sum (t.sum_edw_trx_cnt) ,count(1) from (
select max(x.edw_trx_cnt)sum_edw_trx_cnt, x.prctr_cell_nbr 
from p_prctr_smpl_pf_sp3 x 
where x.mdld_prctr_flg = 'Y' 
group by x.prctr_cell_nbr 
)t;` 

SUM(T.SUM_EDW_TRX_CNT) COUNT(1) 
---------------------------------- 
19838749    14106326 

8

Quello che si vede è l'effetto dell'applicazione dell'opzione di selezione dell'elenco da parte dell'ottimizzatore. In questo caso è considerato un bug - se una vista in linea contiene una funzione aggregata, una o più colonne non referenziate nella query principale e non c'è una clausola group by, l'ottimizzatore decide di eliminare semplicemente quelle colonne senza riferimento (SLP - selezionare l'eliminazione della lista):

Ambiente: Windows x64; Oracle 12.1.0.1.0

-- test-table 
create table t1 as 
    select level as col1 
     , level as col2 
    from dual 
    connect by level <= 7; 

-- gather statistic on t1 table. 
exec dbms_stats.gather_table_stats('', 'T1'); 

Ora cerchiamo di eseguire la query buggy con 10.053 traccia abilitato e vedere cosa accadrà sotto il coperchio:

alter session set tracefile_identifier='no_group_by'; 

alter session set events '10053 trace name context forever'; 

select /*+ qb_name(outer) */ col1 
    from (
     select /*+ qb_name(inner) */ max(col1) as col1 
       , col2 
      from t1 
     ); 


     COL1 
---------- 
     7 

alter session set events '10053 trace name context off'; 

non c'era prevede ORA-00937 errore. Tutto è andato liscio. Ora il file di traccia:

OPTIMIZER INFORMATION 

****************************************** 
----- Current SQL Statement for this session (sql_id=d14y7zuxvvfbw) ----- 
select /*+ qb_name(outer) */ col1 
    from (
     select /*+ qb_name(inner)*/max(col1) as col1 
       , col2 
      from t1 
     ) 
******************************************* 
..... 

Query transformations (QT) 
************************** 
.... 
SVM: SVM bypassed: Single grp set fct (aggr) without group by. 

/* That's where we lose our COL2 */ 

SLP: Removed select list item COL2 from query block INNER 
query block OUTER (#0) unchanged 

.... 

Final query after transformations:******* UNPARSED QUERY IS ******* 
SELECT /*+ QB_NAME ("OUTER") */ "from$_subquery$_001"."COL1" "COL1" 
    FROM (SELECT /*+ QB_NAME ("INNER") */ MAX("T1"."COL1") "COL1" 
      FROM "HR"."T1" "T1") "from$_subquery$_001" 

Per risolvere il problema il parametro _query_rewrite_vop_cleanup può essere impostato per false. Naturalmente, consultate il supporto Oracle se questo parametro deve essere impostato in un ambiente di produzione.

alter session set "_query_rewrite_vop_cleanup"=false; 
session altered 

select /*+ qb_name(outer) */ col1 
    from (
     select /*+ qb_name(inner) */ max(col1) as col1 
       , col2 
      from t1 
     ); 

Risultato:

Error report - 
SQL Error: ORA-00937: not a single-group group function 
00937. 00000 - "not a single-group group function" 

E quando aggiungiamo group by clausola, la query funziona come previsto.

select /*+ qb_name(outer) */ col1 
    from (
     select /*+ qb_name(inner) */ max(col1) as col1 
       , col2 
      from t1 
      group by col2 
     ); 

Risultato:

COL1 
---------- 
     1 
     6 
     2 
     4 
     5 
     3 
     7 

Se si ha accesso a MOS, dare un'occhiata a 1589317.1, 16989676.8 (Bug 16.989.676 - deve essere fissato in 12.1.0.2 release), Bug 8945586 note.

+1

Grazie mille per la tua risposta dettagliata. Ho provato con: alter session set "_query_rewrite_vop_cleanup" = false; e Oracle genera l'errore come previsto. –

+0

Altri voti per questa risposta! – Sebas

Problemi correlati