Duplicating records to fill gap between dates
oracle, oracle-analytics, sql
Solution
I think I have a solution using an incremental approach toward the final result with CTE's:
with mindate as
(
select min(price_date) as mindate from PRICES_TEST
)
,dates as
(
select mindate.mindate + row_number() over (order by 1) - 1 as thedate from mindate,
dual d connect by level <= floor(SYSDATE - mindate.mindate) + 1
)
,productdates as
(
select p.product, d.thedate
from (select distinct product from PRICES_TEST) p, dates d
)
,ranges as
(
select
pd.product,
pd.thedate,
(select max(PRICE_DATE) from PRICES_TEST p2
where p2.product = pd.product and p2.PRICE_DATE <= pd.thedate) as mindate
from productdates pd
)
select
r.thedate,
r.product,
p.price
from ranges r
inner join PRICES_TEST p on r.mindate = p.price_date and r.product = p.product
order by r.product, r.thedate
- `mindate` retrieves the earliest possible date in the data set
- `dates` generates a calendar of dates from earliest possible date to today.
- `productdates` cross joins all possible products with all possible dates
- `ranges` determines which price date applied at each date
- the final query links which price date applied to the actual price and filters out dates for which there are no relevant price dates via the `inner join` condition
Demo: http://www.sqlfiddle.com/#!4/e528f/126
Problem
I need to do something really weird, which is to create fake records in a view to fill the gap between posted dates of product prices. Actually, my scenario is a little bit more complicated than that, but I've simplified to products/dates/prices. Let's say we have this table: ``` create table PRICES_TEST ( PRICE_DATE date not null, PRODUCT varchar2(13) not null, PRICE number ); alter table PRICES_TEST add constraint PRICES_TEST_PK primary key (PRICE_DATE, PRODUCT); ``` With these records: ``` insert into PRICES_TEST values (date'2012-04-15', 'Screw Driver', 13); insert into PRICES_TEST values (date'2012-04-18', 'Screw Driver', 15); insert into PRICES_TEST values (date'2012-04-13', 'Hammer', 10); insert into PRICES_TEST values (date'2012-04-16', 'Hammer', 15); insert into PRICES_TEST values (date'2012-04-19', 'Hammer', 17); ``` selecting records will return me this: ``` PRICE_DATE PRODUCT PRICE ------------------------- ------------- ---------------------- 13-Apr-2012 00:00:00 Hammer 10 16-Apr-2012 00:00:00 Hammer 15 19-Apr-2012 00:00:00 Hammer 17 15-Apr-2012 00:00:00 Screw Driver 13 18-Apr-2012 00:00:00 Screw Driver 15 ``` Assuming today is Apr 21 2012, I need a view that shall repeat each price every day until a new price is posted. Like this: ``` PRICE_DATE PRODUCT PRICE ------------------------- ------------- ---------------------- 13-Apr-2012 00:00:00 Hammer 10 14-Apr-2012 00:00:00 Hammer 10 15-Apr-2012 00:00:00 Hammer 10 16-Apr-2012 00:00:00 Hammer 15 17-Apr-2012 00:00:00 Hammer 15 18-Apr-2012 00:00:00 Hammer 15 19-Apr-2012 00:00:00 Hammer 17 20-Apr-2012 00:00:00 Hammer 17 21-Apr-2012 00:00:00 Hammer 17 15-Apr-2012 00:00:00 Screw Driver 13 16-Apr-2012 00:00:00 Screw Driver 13 17-Apr-2012 00:00:00 Screw Driver 13 18-Apr-2012 00:00:00 Screw Driver 15 19-Apr-2012 00:00:00 Screw Driver 15 20-Apr-2012 00:00:00 Screw Driver 15 21-Apr-2012 00:00:00 Screw Driver 15 ``` Any ideas how to do that? I cannot really use other auxiliary tables, triggers nor PL/SQL programming, I really need to do this using a view. I think this can be done using oracle analytics, but I'm not familiar with that. I tried to read this http://www.club-oracle.com/articles/analytic-functions-i-introduction-164/ but I didn't get it at all.