我有以下数据:
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
即。创建缺少日期,重复产品代码并计算金额。
答案 0 :(得分:5)
使用LEAD函数和hierarchical查询的组合,可以在单个查询中实现。
演示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
此处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
答案 1 :(得分:3)
我假设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;