没有group by的Oracle结果

时间:2014-12-05 18:39:33

标签: sql oracle oracle11g

我在Oracle Exadata上运行查询。

  

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的输出,这是内部查询的最大计数。

我对此行为感到困惑,因为这不是查询返回的正确结果。我不认为这是一种已知的行为,最近有人见过吗?

由于

2 个答案:

答案 0 :(得分: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.116989676.8(错误16989676 - 应在12.1.0.2版本中修复),Bug 8945586注释。

答案 1 :(得分: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