【发布时间】:2019-01-04 19:52:56
【问题描述】:
在 Oracle 12.2 的 group by 子句中的聚合函数上使用 order by 时,我们收到不正确的结果排序。在玩弄它之后,我们发现该查询仅在以某些方式表达时才有效(见下文)。
这是我们的问题:
1) 为什么按 avg 进行排序很挑剔?查询是否基于某些记录的逻辑/限制按预期运行?是否与底层数据类型为 number(16) 没有小数位有关?
2) 为什么在查询 4 中使用别名可以使它工作,而查询 3 却不起作用?
3) 为什么查询在按持续时间升序排序时效果更好?它没有在下面显示,但是查询 2 在 asc 时有效,即使它不工作 desc。查询 1 不适用于 asc。
在下面的示例中,请注意持续时间是一个数字 (16)。
查询 1:按函数平均函数顺序
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
查询 2:按别名平均函数顺序
-- 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
查询 3:按函数转换顺序的平均函数
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
查询 4:按别名转换顺序的平均函数
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
查询 5 和 6:在外部查询中带/不带强制转换的平均函数
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
【问题讨论】:
-
您的错误结果完全是错误的(假设查询是准确的)。这似乎是您正在使用的 Oracle 版本中的一个错误。
-
对我来说也像一个错误。前提是,只有一个表有一个名为
duration的列,并且两个表中没有一个名为avg的列 -
查看每个查询的执行计划,这可能会显示优化器执行的转换可能在逻辑上是错误的,也可能不是。无论如何 - 您能否发布一个最小的数据样本(您的两个表,列尽可能少,同时仍然能够重新创建您报告的错误行为)?
-
确实是个bug。它在优化器决定使用 VW_GBC_5 时显示。请参阅下面的答案。