这个查询看起来很有希望:
select *
from (
with
data as (select row_number() over (order by m_dt) rn, dat.* from dat),
numbers as (select level n from dual connect by level<=10)
select rn, m_dt, n, 0 flags,
(select avg(koef) from data where rn not between d.rn and d.rn + n - 1) av
from data d, numbers
union all
select rn, m_dt, n, 1,
(select avg(koef) from data
where flag = 1 or rn not between d.rn and d.rn + n - 1) av
from data d, numbers
order by av desc)
where rownum = 1
我希望我正确理解了您的讨论和说明,但即使没有 - 也许其中一些代码会有用。
对于表查询中的每个日期,会消除 1 到 10 个连续的行,其余行计数 avg。
当我们将 flag=1 的行添加到消除集时也是如此。外部查询选择平均值最高的行。
这里也是 PL/SQL 版本(远非最佳,我只是写了一些东西来检查 SQL 解决方案的结果 -
两种解决方案都产生了相同的最佳方案):
create or replace procedure miner is
v_best_avg number := 0;
v_curr_avg number := 0;
v_max_cnt number := 10;
begin
for v_cnt in 1..v_max_cnt
loop
for o in (select row_number() over (order by m_dt) rn, dat.* from dat)
loop
select avg(koef) into v_curr_avg
from (select row_number() over (order by m_dt) rn, dat.* from dat)
where rn not between o.rn and o.rn + v_cnt - 1;
if v_curr_avg > v_best_avg then
v_best_avg := v_curr_avg;
dbms_output.put_line(trunc(v_curr_avg, 4)||' '
||to_char(o.m_dt, 'yyyy-mm-dd')||' '||v_cnt||' '||'flags not excluded');
end if;
select avg(koef) into v_curr_avg
from (select row_number() over (order by m_dt) rn, dat.* from dat)
where flag = 1 or rn not between o.rn and o.rn + v_cnt - 1;
if v_curr_avg > v_best_avg then
v_best_avg := v_curr_avg;
dbms_output.put_line(trunc(v_curr_avg, 4)||' '
||to_char(o.m_dt, 'yyyy-mm-dd')||' '||v_cnt||' '||'flags not excluded');
end if;
end loop;
end loop;
end miner;