2014-12-05 2 views
9

Я выполняю ниже запрос по Oracle Exadata.Результат Oracle без группы

Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit производства С секционирования, Real Application Clusters, автоматическое управления хранением, OLAP, интеллектуального анализа данных и Real Application Testing опции

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

То, что вы видите, - это эффект от применения «выбора списка обрезки» оптимизатором. В этом случае это считается ошибкой - если встроенное представление содержит агрегированную функцию, неопубликованный столбец (-ы) в основном запросе и не существует group by, оптимизатор решает просто избавиться от тех неучтенных столбцов (SLP - выбивка списка выбора):

Окружающая среда: 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'); 

Теперь давайте выполним этот ошибочный запрос с 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.1, 16989676.8 (ошибка 16989676 - должна быть исправлена ​​в 12.1.0.2 выпуске), Bug 8945586 ноты.

+1

Большое спасибо за подробный ответ. Я попытался: изменить набор сеансов «_query_rewrite_vop_cleanup» = false; и Oracle генерирует ошибку, как ожидалось. –

+0

Больше очков для ответа! – Sebas

Смежные вопросы