2014-12-05 24 views
9

我在Oracle Exadata上查詢下面。Oracle結果沒有組

Oracle數據庫11g企業版發佈11.2.0.4.0 - 64位生產與分隔,真正應用集羣,自動 存儲管理,OLAP,數據挖掘和實時應用測試 選項

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; 

我期待oracle會返回一個錯誤,因爲 - 你可以看到在內部查詢「t」中沒有group by子句,我期待這個查詢失敗。

有數百萬條記錄,並且對於每個prctr_cell_nbr我想要最大計數,然後外部查詢應該總計每個prctr_cell的最大計數。 這是一個簡單的查詢。 但是,查詢運行並返回112的輸出,它是來自內部查詢的最大計數。

我很困惑這種行爲,因爲這不是查詢返回的正確結果。我不認爲這是一個已知的行爲,有沒有人最近看到這個?

感謝

+0

但是,如果你只是運行內部選擇正確,你會得到一個錯誤? – xQbert 2014-12-05 18:55:19

+0

是的。如果單獨運行,則內部查詢會導致錯誤。 – 2014-12-05 18:59:28

+0

http://dba.stackexchange.com/questions/39674/why-is-a-non-single-group-group-function-allowed-in-a-subselect-but-not-on-it – Multisync 2014-12-05 19:18:56

回答

0

我不認爲如果group by子句被排除的結果可能是正確的。 僅當內部查詢產生的 單個記錄與排除逐列相同時,外部查詢的結果纔是正確的。

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

您看到的是優化程序應用「選擇列表修剪」的效果。在這種情況下,它被認爲是一個錯誤 - 如果一個內嵌視圖包含聚合函數,主查詢中的未引用列,並且沒有group by子句,優化器將決定簡單地刪除那些未引用的列( SLP - 選擇列表修剪):

環境:Windows x64;甲骨文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'); 

現在讓我們執行與啓用10053痕跡是越野車查詢和看到的掩護下,會發生什麼:

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'; 

有沒有預期ORA-00937錯誤。一切順利。現在跟蹤文件:

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" 

變通方法是_query_rewrite_vop_cleanup參數可以設置爲false。但是,如果需要在生產環境中設置此參數,當然需要諮詢oracle支持。

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 
     ); 

結果:

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

當我們添加group by子句,查詢工作正常。

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

結果:

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

如果你有機會獲得MOS,看看1589317.116989676.8(錯誤16989676 - 應固定在12.1.0.2版本),Bug 8945586筆記。

+1

非常感謝您的詳細回覆。我試着用:alter session set「_query_rewrite_vop_cleanup」= false;並且Oracle按預期拋出錯誤。 – 2014-12-05 22:04:01

+0

更多upvotes爲了這個答案! – Sebas 2014-12-05 22:40:21