Đ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ú.
Tuy nhiên, bạn sẽ gặp lỗi nếu bạn chỉ chạy bên trong chọn đúng? – xQbert
Có. Kết quả truy vấn bên trong bị lỗi nếu chạy riêng. –
http://dba.stackexchange.com/questions/39674/why-is-a-non-single-group-group-function-allowed-in-a-subselect-but-not-on-it – Multisync