在Oracle 12.2的group by子句中的聚合函数上使用order by时,我们收到的结果排序不正确。在使用它之后,我们发现该查询仅在以某些方式用词组表达时才有效(请参见下文)。
这是我们的问题:
1)为什么按Avg排序很挑剔?查询是否基于某些已记录的逻辑/限制而按预期运行?是否与底层数据类型为number(16)而没有小数位数有关?
2)为什么在查询4中使用别名却使查询3无效?
3)为什么按持续时间递增排序时查询工作更好?它未在下面显示,但查询2在使用asc时仍然有效,即使它在desc中也不起作用。查询1不适用于asc。
在以下示例中,持续时间是一个数字(16)。
select
name,
avg(duration)
from table1
join table2 on table1.table2_id = table2.id
where duration is not null
group by name
order by avg(duration) desc
-- Query 1 result (wrong)
(some name) 1224417.83471074
(some name) 33568438.1548673
(some name) 3928150.12809406
(some name) 1434939.13464658
(some name) 269338.574638521
-- Query 2: order by avg alias
select
name,
avg(duration) avg
from table1
join table2 on table1.table2_id = table2.id
where duration is not null
group by name
order by avg desc
-- Query 2 result (wrong)
-- See query 1 result
-- Note: For some reason this query works correctly when ordered asc
select
name,
to_number(avg(duration))
from table1
join table2 on table1.table2_id = table2.id
where duration is not null
group by name
order by to_number(avg(duration)) desc
-- Query 3 result (wrong)
-- See query 1 result
select
name,
to_number(avg(duration)) avg
from table1
join table2 on table1.table2_id = table2.id
where duration is not null
group by name
order by avg desc
-- Query 4 results (correct)
(some name) 562654936
(some name) 498804314
(some name) 263681023
(some name) 245531731
(some name) 188103278
-- the values with decimals show up later in the right order
select * from (
select
name,
to_number(avg(duration)) avg -- works without to_number as well
from table1
join table2 on table1.table2_id = table2.id
where duration is not null
group by name
) order by avg desc
-- Query 5 & 6 results (correct)
-- See query 4 results
答案 0 :(得分:1)
我猜要获得正确的输出结果,您需要已经进行了聚合,但是这里发生的是在按您进行聚合的顺序再次分组之后完成聚合时,因此即使已经完成的聚合也可以再次开始聚合它的别名是使用外部查询最有效的方法是:首先在汇总后最终确定输出,然后在外部查询中像select col1,col2 from (select col,agg(..) from table group by col) order by col2
那样进行排序,这将限制为仅对接收到的输出进行排序,而不会再次进行聚合和排序。
答案 1 :(得分:0)
我们已将其追溯到我们认为是Oracle优化器中的错误。当优化器选择使用称为VW_GBC_5的视图时,就会发生这种情况。请遵守以下说明计划:
有问题
-- This produces incorrect result set ordering
select
/*+ qb_name(m) place_group_by(@m) */
name,
avg(duration)
from table1
join table2 on table1.table2_id = table2.id
where duration is not null
group by name
order by avg(duration) desc;
-------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 35540 | 3366K| | 9433 (1)| 00:00:01 |
| 1 | SORT ORDER BY | | 35540 | 3366K| 3800K| 9433 (1)| 00:00:01 |
| 2 | HASH GROUP BY | | 35540 | 3366K| 3800K| 9433 (1)| 00:00:01 |
|* 3 | HASH JOIN | | 35540 | 3366K| | 7852 (1)| 00:00:01 |
| 4 | VIEW | VW_GBC_5 | 35540 | 1145K| | 7510 (2)| 00:00:01 |
| 5 | HASH GROUP BY | | 35540 | 416K| | 7510 (2)| 00:00:01 |
|* 6 | TABLE ACCESS FULL| TABLE1 | 1225K| 14M| | 7461 (1)| 00:00:01 |
| 7 | TABLE ACCESS FULL | TABLE2 | 38955 | 2434K| | 342 (1)| 00:00:01 |
-------------------------------------------------------------------------------------------------
没有问题
-- This produces correct result set ordering
select
/*+ qb_name(m) no_place_group_by(@m) */
name,
avg(duration)
from table1
join table2 on table1.table2_id = table2.id
where duration is not null
group by name
order by avg(duration) desc;
-----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 38412 | 2850K| | 25624 (1)| 00:00:02 |
| 1 | SORT ORDER BY | | 38412 | 2850K| 98M| 25624 (1)| 00:00:02 |
| 2 | HASH GROUP BY | | 38412 | 2850K| 98M| 25624 (1)| 00:00:02 |
|* 3 | HASH JOIN | | 1225K| 88M| 2896K| 9345 (1)| 00:00:01 |
| 4 | TABLE ACCESS FULL| TABLE2 | 38955 | 2434K| | 342 (1)| 00:00:01 |
|* 5 | TABLE ACCESS FULL| TABLE1 | 1225K| 14M| | 7461 (1)| 00:00:01 |
-----------------------------------------------------------------------------------------------
解决方法
重写查询(请参阅原始问题)
禁用_simple_view_merging
更改会话集“ _simple_view_merging” = false;
切换到其他优化器版本
更改会话集optimizer_features_enable = '12 .1.0.2';
使用no_place_group_by优化器提示