[英]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函数和层次查询,可以在单个查询中实现。
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.