【问题标题】:Need advise in calculating best ratio在计算最佳比率时需要建议
【发布时间】:2015-05-20 22:25:11
【问题描述】:

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

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

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

主要思想是通过根据上限条件从计算中排除行来获得最高的 avg koef。

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

【问题讨论】:

  • “我需要一一排除日期(列 cnt)的数量” - 不清楚。你有没有试过任何查询?
  • 我有一些机制,但是很难查询,这里不能发。
  • 作为更好理解问题的示例。例如 100 行的 avg koef 我有 2.4,我看到 25-28 行有 koef 1-2。我通过将最后一列(can_exclude)更新为 1 来排除这些行,并根据排除的行 2.7 获取平均值。
  • 我不清楚第一个排除。 select (select sum(koef) from dat where can_exclude=0)/(select count(*) from dat where can_exclude=0) AS Average from dual; 试试这个查询。在 where 子句中添加您的第一个排除逻辑。
  • 我希望你理解我:) 我需要排除一些行。无论如何,它可以是 pl/sql 或只是 sql 查询。毕竟操纵得到最好的 avg koef

标签: oracle plsql


【解决方案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;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-13
    • 1970-01-01
    • 1970-01-01
    • 2012-04-19
    相关资源
    最近更新 更多