需要建议计算最佳比例

时间:2015-05-20 09:43:37

标签: oracle plsql

所以,我有一些with_options的表结构(使用此链接获取信息)

我需要从0到10(在示例中)逐个排除日期数(列cnt),还可以排除列标志中值为1的其他列。

最后,我需要根据非排除值获得最高的koef平均值。

主要思想是根据较高的条件,通过从计算中排除行来获得最高平均值。

任何人都知道如何处理这项任务?

1 个答案:

答案 0 :(得分:1)

此查询看起来很有希望:

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;