1

我有以下数据:

date          product    amount
2013-01-31    a1           100
2013-02-28    a1           200
2013-01-31    b1           700
2013-04-30    b1           100
2013-06-30    b1          1300
2013-03-31    c1            10
2013-07-31    c1            70

是否可以在 sql/plsql 中创建基于日期填充缺失行的查询?我的意思是我想得到以下结果:

date          product    amount
 2013-01-31    a1           100
 2013-02-28    a1           200
 2013-01-31    b1           700
*2013-02-28    b1           500*
*2013-03-31    b1           300*
 2013-04-30    b1           100
*2013-05-31    b1           700*
 2013-06-30    b1          1300
 2013-03-31    c1            10
*2013-04-30    c1            25*
*2013-05-31    c1            40*
*2013-06-30    c1            55*
 2013-07-31    c1            70

即创建缺少的日期,复制产品代码并计算金额。

4

2 回答 2

5

使用LEAD函数和分层查询的组合,这可以在单个查询中实现。

演示在这里

    SELECT DISTINCT
           ADD_MONTHS (product_date, LEVEL - 1), product, amount + ( (LEVEL - 1) * mul_factor)
      FROM (SELECT product_date, product, amount, next_date,
                   amount_diff / month_diff mul_factor
              FROM (SELECT product_date, product, amount,
                           LEAD (product_date, 1) OVER (PARTITION BY product ORDER BY product_date)
                              AS next_date,
                           MONTHS_BETWEEN (
                              (LEAD (product_date, 1) OVER (PARTITION BY product ORDER BY product_date)),
                              product_date)
                              AS month_diff,
                           LEAD (amount, 1) OVER (PARTITION BY product ORDER BY product_date)
                              AS next_amount,
                             LEAD (amount, 1) OVER (PARTITION BY product ORDER BY product_date)
                           - amount
                              AS amount_diff
                      FROM mytable)
             WHERE next_date IS NOT NULL)
CONNECT BY ADD_MONTHS (product_date, LEVEL - 1) <= next_date
  ORDER BY 2, 1

这里 LEAD 函数用于获取下一个日期和下一个金额。使用它,可以找到平均分配金额所需的月份差异、金额差异和价值差异。这稍后在层次查询中用于获取开始日期和结束日期之间的所有月份。但这给出了几个重复的行,我似乎无法消除。因此使用了 DISTINCT 关键字。

输出:

01/31/2013    a1    100
02/28/2013    a1    200
01/31/2013    b1    700
02/28/2013    b1    500
03/31/2013    b1    300
04/30/2013    b1    100
05/31/2013    b1    700
06/30/2013    b1    1300
03/31/2013    c1    10
04/30/2013    c1    25
05/31/2013    c1    40
06/30/2013    c1    55
07/31/2013    c1    70
于 2013-07-13T05:29:57.580 回答
2

我假设 product_amounts 是该表的名称。

declare
  n integer;
  i integer;
  a integer;
  d date;
begin
  for x in
  (
    select *
    from   ( select product,
                    amount,
                    trunc(date, 'MONTH') mon,
                    lead(trunc(date, 'MONTH')) over(partition by product order by date) next_mon,
                    lead(amount) over(partition by product order by date) next_amount,
             from   product_amounts
           )
    where  months_between(next_mon, mon) > 1
  )
  loop
    n := months_between(x.next_mon, x.mon);
    for i in 1 .. n-1
    loop
      d := add_months(x.mon, i);
      a := x.amount + (x.next_amount - x.amount)/n;

      insert into product_amounts(date, product, amount)
      values (last_day(d), x.product, a);
    end loop;
  end loop;

  commit;
end;
于 2013-07-12T21:51:53.143 回答