2014-12-05 2 views
9

Oracle Exadata에 대한 쿼리가 실행 중입니다.오라클 결과 (그룹 제외)

오라클 데이터베이스 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; 

오라클이 다음과 같은 오류를 반환 할 것으로 예상했습니다. - 내부 쿼리 "t"에 group by 절이 없으므로이 쿼리가 실패 할 것으로 예상했습니다.

수백만 개의 레코드가 있으며 각각에 대해 prctr_cell_nbr 최대 개수를 원하고 외부 쿼리는 모든 prctr_cell에 대해 최대 개수를 합산해야합니다. 간단한 쿼리입니다. 그러나 쿼리가 실행되고 내부 쿼리에서 최대 카운트 인 112의 결과를 반환합니다.

이것은 올바른 결과가 쿼리에서 반환 된 것이 아니기 때문에이 동작에 의아해합니다. 나는 이것이 알려진 행동이라고 생각하지 않는다. 최근에 누군가를 보았는가?

감사합니다.

+0

내부 선택을 올바르게 실행하면 오류가 발생합니까? – xQbert

+0

예. 별도로 실행하면 내부 쿼리 결과가 오류가 발생합니다. –

+0

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

답변

0

그룹 별 절을 제외하면 결과가 정확하지 않을 것이라고 생각합니다. 외부 쿼리의 결과는 내부 쿼리가 열 단위 그룹 제외와 동일한 단일 레코드 인 을 생성 할 때만 정확합니다.

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

옵티마이 저가 "select list pruning"을 적용하면 효과가 나타납니다. 이 경우 버그로 간주됩니다. 인라인 뷰에 집계 함수, 기본 쿼리의 참조되지 않은 열이 포함되어 있고 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 오류를 예상 없었다. 모든 것이 순조롭게 진행되었습니다. 이제 추적 파일 다음 _query_rewrite_vop_cleanup 매개 변수가 false로 설정 할 수있는 해결 방법으로

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" 

. 그러나 프로덕션 환경에서이 매개 변수를 설정해야하는 경우 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 
     ); 

결과 : 당신이 MOS에 액세스 할 수있는 경우

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

,보고 1589317.1에서 16989676.8 걸릴 (버그 16989676이 - 12.1.0.2 릴리스에서 해결되어야한다), Bug 8945586 메모를.

+1

답장을 보내 주셔서 감사합니다. 나는 다음과 같이 시도했다. "_query_rewrite_vop_cleanup"= false로 세션을 변경한다. Oracle은 예상대로 오류를 발생시킵니다. –

+0

이 답변에 대한 더 많은 상향 투표! – Sebas