“基于...的过度分区”查询的基数错误

时间:2019-07-09 10:44:59

标签: sql oracle oracle12c window-functions

在Oracle 12.1.0.2上,我有一个表,代码为send_date和send_id为pk

我需要为每个值的最后一次发送代码获取一些值。

select  * from (
select code, some_column,
row_number() over (partition by code order by send_date desc, send_id desc) n
from my_table
) where n=1

由于“其中n = 1”,Oracle对基数进行了1行的估计,因此,对于使用以前的SQL作为子查询的复杂查询,选择一个非常糟糕的执行计划。

我认为这是一个Oracle错误 https://support.oracle.com/knowledge/Oracle%20Database%20Products/2118138_1.html

是否有任何替代方法可以绕过此错误?

1 个答案:

答案 0 :(得分:0)

这可能是错误,也可能不是。根据可用的统计信息,很可能这只是优化程序的失败。

对于您的查询以及下面的查询,我建议在 SELECT JSON_OBJECT(s.name, GROUP_CONCAT(srs.record)) AS record FROM statuses AS s INNER JOIN (SELECT JSON_OBJECT(u.name, GROUP_CONCAT(date)) AS record, status_id FROM status_records AS sr JOIN users u ON u.id = sr.user_id GROUP BY u.id, status_id) srs ON srs.status_id = s.id GROUP BY s.id; 上使用索引。

以下是编写查询的两种替代方法,因此您可以比较性能:

(code, send_date desc, send_id desc, some_column)

并且:

select code, 
       max(some_column) keep (dense rank first order by send_date desc, send_id desc) as somecolumn
from my_table
group by code;