Sql 在oracle中计算滚动加权平均值

Sql 在oracle中计算滚动加权平均值,sql,oracle,oracle12c,Sql,Oracle,Oracle12c,我有一个数据子集,看起来像这样: create table tbl_1 as ( select * from ( select trunc(sysdate - (rownum - 1)) as call_dt, rownum as calls, to_char(trunc(sysdate - (rownum - 1)), 'DAY') as dow from dual connect by row

我有一个数据子集,看起来像这样:

create table tbl_1 as (
    select * from (
        select trunc(sysdate - (rownum - 1)) as call_dt,
               rownum as calls,
               to_char(trunc(sysdate - (rownum - 1)), 'DAY') as dow
        from dual connect by rownum <= 22
    )
    where dow like '%MONDAY%'
    order by call_dt
)
;

 call_dt  | calls | dow
-------------------------
17-SEP-18    22    MONDAY   
24-SEP-18    15    MONDAY   
01-OCT-18    8     MONDAY   
08-OCT-18    1     MONDAY 
create table tbl_2 as (
    select * from (
        select  trunc(sysdate + (rownum - 1)) as call_dt, 
                0 as calls,
                to_char(trunc(sysdate + (rownum - 1)), 'DAY') as dow
        from dual
        connect by rownum <= 15
    )
    where dow like '%MONDAY%'
)
;

 call_dt  | calls | dow
-------------------------
15-OCT-18     0    MONDAY   
22-OCT-18     0    MONDAY
其结果如下:

 call_dt  | calls | dow
-------------------------
17-SEP-18    22    MONDAY   
24-SEP-18    15    MONDAY   
01-OCT-18    8     MONDAY   
08-OCT-18    1     MONDAY 
15-OCT-18    46    MONDAY   
22-OCT-18    24    MONDAY
这对于一周中的每一天的第一个未来日期都非常有效。但是,对于后续日期,
lag*
变量等于0,因此该值为off。以下是我希望实现的目标:

 call_dt  | calls | dow
-------------------------
17-SEP-18    22    MONDAY   
24-SEP-18    15    MONDAY   
01-OCT-18    8     MONDAY   
08-OCT-18    1     MONDAY 
15-OCT-18    46    MONDAY   
22-OCT-18    70    MONDAY

我看了看,好像它能给我想要的?但是使用的窗口函数关键字对我来说是陌生的。我也看了,但这些滚动平均函数似乎假设了非零项。有可能实现这些结果吗?

使用递归查询,它将最后的
调用
视为
lag1
,并将所有其他
lag
移动到过去:

with 
  s as (
    select  rn, call_dt, calls, 
            lag(calls, 4) OVER (partition by dow order by call_dt) as lag4,
            lag(calls, 3) OVER (partition by dow order by call_dt) as lag3,
            lag(calls, 2) OVER (partition by dow order by call_dt) as lag2,
            lag(calls, 1) OVER (partition by dow order by call_dt) as lag1
    from (
        select 0 rn, tbl_1.* from tbl_1 union all
        select row_number() over (order by call_dt), tbl_2.* from tbl_2)),
  c(rn, call_dt, calls, lag1, lag2, lag3, lag4) as (
    select rn, call_dt, (1 * lag1) + (0.8 * lag2) + (0.5 * lag3) + (0.3 * lag4), 
           lag1, lag2, lag3, lag4 
      from s where rn = 1
    union all
    select s.rn, s.call_dt, (1 * c.calls) + (0.8 * c.lag1) + (0.5 * c.lag2) + (0.3 * c.lag3), 
           c.calls, c.lag1, c.lag2, c.lag3
      from s join c on c.rn+1 = s.rn)
select * from c
s
-基本上是您的查询,我在其中添加了行编号
c
是CTE,其中
rn=1
是我们的第一步。然后我们逐行添加后续步骤, 将以前的值向右移动。我想我们应该把结果除以4,但你们并没有这样做?希望这有帮助

结果:

    RN CALL_DT          CALLS       LAG1       LAG2       LAG3       LAG4
------ ----------- ---------- ---------- ---------- ---------- ----------
     1 2018-10-15        21,5          1          8         15         22
     2 2018-10-22        30,8       21,5          1          8         15

您使用的是什么版本的Oracle?最简单的方法可能是递归CTE。您知道这个方法吗?可能是
介于前一天的间隔“4”和后一天的间隔“4”之间
@GordonLinoff我使用的是这个版本:
Oracle数据库12c企业版12.2.0.1.0-64位生产版
@WernfriedDomscheit我不熟悉windowing\u子句。您能否详细介绍一下前一个间隔“4”天和后一个间隔“4”天之间的
工作原理?这是否会在Oracle当前运行行的日期周围创建一个+/-4天的窗口?是的,这就是它的工作方式。Oracle在这个例子中使用+/-4天,不管这个范围覆盖了多少行。是的,结果应该除以4得到平均值,但我忘了包括它,不想通过更改它来引起混乱。你的结果看起来不错,但我需要花一些时间摸索解决方案。在我回顾的过程中,您能否澄清此解决方案在其处理的未来日期范围内是否是动态的,或者该解决方案是否假定只有两周的预测时间?提前感谢您!刚刚测试了一切,这一切都很完美!非常感谢你!
    RN CALL_DT          CALLS       LAG1       LAG2       LAG3       LAG4
------ ----------- ---------- ---------- ---------- ---------- ----------
     1 2018-10-15        21,5          1          8         15         22
     2 2018-10-22        30,8       21,5          1          8         15