简体   繁体   English

在Oracle SQL中填充缺少的行

[英]populating missing rows in oracle sql

I have following data: 我有以下数据:

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

Is it possible to create query in sql/plsql that would populate missing rows based on dates? 是否可以在sql / plsql中创建查询,以根据日期填充缺少的行? I mean i would like to get following result: 我的意思是我想得到以下结果:

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

ie create missing dates, duplicate product code and calculate amount. 即创建缺少的日期,重复产品代码并计算数量。

Using a combination of LEAD function and hierarchical queries, this can be achieved in a single query. 结合使用LEAD函数和层次查询,可以在单个查询中实现。

Demo here . 演示在这里

    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

Here LEAD function is used to get the next date and next amount. LEAD函数用于获取下一个日期和下一个金额。 Using this, the difference in the months, difference in amount and value required to evenly distribute the amount can be found. 使用此方法,可以发现月份差异,金额差异和均匀分配金额所需的价值。 This is later used in hierarchal query to get all the months between the start and end dates. 以后在层次结构查询中使用它来获取开始日期和结束日期之间的所有月份。 But this gives several duplicate rows, which i can't seem to eliminate. 但这给出了几个重复的行,我似乎无法消除。 Hence have used DISTINCT keyword. 因此使用了DISTINCT关键字。

Output: 输出:

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

I assume that product_amounts is the name of this table. 我假设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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM