2014-12-05 19 views
9

Tôi đang chạy bên dưới truy vấn trên Oracle Exadata.Kết quả Oracle không có nhóm theo số

Oracle Database 11g Enterprise Edition phiên bản 11.2.0.4.0 - Sản xuất 64bit Với ​​phân vùng, Clusters Application Real, quản lý lưu trữ tự động , OLAP, Khai thác dữ liệu và Real Application Testing tùy chọn

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ôi đã mong đợi oracle trả về lỗi vì - Như bạn có thể thấy không có mệnh đề group by trong truy vấn bên trong “t” và tôi đã mong truy vấn này thất bại.

Có hàng triệu bản ghi và cho mỗi prctr_cell_nbr Tôi muốn số lượng tối đa và sau đó truy vấn bên ngoài sẽ tổng hợp số lượng tối đa cho mỗi prctr_cell. Đó là một truy vấn đơn giản. Tuy nhiên, truy vấn chạy và trả về kết quả của 112 là số lượng tối đa từ truy vấn bên trong.

Tôi đang bối rối bởi hành vi này vì đây không phải là kết quả chính xác được trả về bởi truy vấn. Tôi không nghĩ rằng đây là một hành vi đã biết, có ai nhìn thấy điều này gần đây không?

Cảm ơn

+0

Tuy nhiên, bạn sẽ gặp lỗi nếu bạn chỉ chạy bên trong chọn đúng? – xQbert

+0

Có. Kết quả truy vấn bên trong bị lỗi nếu chạy riêng. –

+0

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

Trả lời

0

Tôi không nghĩ kết quả có thể đúng nếu nhóm theo khoản bị loại trừ. Kết quả của truy vấn bên ngoài sẽ chỉ đúng khi truy vấn bên trong tạo ra bản ghi duy nhất giống như loại trừ nhóm theo cột.

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

Điều bạn thấy là hiệu ứng áp dụng "chọn lược bớt danh sách" bởi trình tối ưu hóa. Trong trường hợp này, nó được coi là lỗi - nếu một dạng xem trực tuyến chứa hàm tổng hợp, cột không được tham chiếu trong truy vấn chính và không có mệnh đề group by, trình tối ưu hóa quyết định loại bỏ các cột không được trả lời này (SLP - chọn danh sách cắt tỉa):

Môi trường: 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'); 

Bây giờ chúng ta hãy thực hiện truy vấn buggy với 10.053 dấu vết kích hoạt và xem những gì sẽ xảy ra dưới bìa:

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

Không có dự kiến ​​ORA-00937 lỗi. Mọi thứ suôn sẻ. Bây giờ các dấu vết tập tin:

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" 

Là một workaround tham số _query_rewrite_vop_cleanup có thể được thiết lập để false. Nhưng tất nhiên tham khảo ý kiến ​​hỗ trợ oracle nếu tham số này cần phải được thiết lập trong một môi trường sản xuất.

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

Kết quả:

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

Và khi chúng tôi thêm group by khoản, truy vấn hoạt động như mong đợi.

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

Kết quả:

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

Nếu bạn có quyền truy cập vào MOS, hãy nhìn vào 1589317.1, 16989676.8 (Bug 16.989.676 - cần được cố định trong 12.1.0.2 phát hành), Bug 8945586 ghi chú.

+1

Cảm ơn bạn rất nhiều vì đã trả lời chi tiết của bạn. Tôi đã thử với: thay đổi phiên thiết lập "_query_rewrite_vop_cleanup" = false; và Oracle ném lỗi như mong đợi. –

+0

Nhiều phiếu bầu khác cho câu trả lời này! – Sebas

Các vấn đề liên quan