L. *_*nda 8 sql oracle relational-database oracle-analytics
我需要做一些非常奇怪的事情,即在视图中创建虚假记录以填补产品价格的发布日期之间的差距.
实际上,我的情况比这复杂一点,但我已经简化为产品/日期/价格.
假设我们有这张表:
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);
Run Code Online (Sandbox Code Playgroud)
有了这些记录:
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);
Run Code Online (Sandbox Code Playgroud)
选择记录将返回给我:
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
Run Code Online (Sandbox Code Playgroud)
假设今天是2012年4月21日,我需要一个视图,每天重复每个价格,直到新价格发布.像这样:
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
Run Code Online (Sandbox Code Playgroud)
任何想法如何做到这一点?我不能真正使用其他辅助表,触发器或PL/SQL编程,我真的需要使用视图来做到这一点.
我认为这可以使用oracle分析完成,但我不熟悉.我试着读这个http://www.club-oracle.com/articles/analytic-functions-i-introduction-164/,但我根本没有得到它.
您可以使用CONNECT BY LEVEL语法创建行生成器语句,与表中的不同产品交叉连接,然后将外部连接到您的价格表.最后一步是使用该LAST_VALUE函数并IGNORE NULLS重复价格直到遇到新值,并且因为您想要一个视图,并带有一个CREATE VIEW语句:
create view dense_prices_test as
select
dp.price_date
, dp.product
, last_value(pt.price ignore nulls) over (order by dp.product, dp.price_date) price
from (
-- Cross join with the distinct product set in prices_test
select d.price_date, p.product
from (
-- Row generator to list all dates from first date in prices_test to today
with dates as (select min(price_date) beg_date, sysdate end_date from prices_test)
select dates.beg_date + level - 1 price_date
from dual
cross join dates
connect by level <= dates.end_date - dates.beg_date + 1
) d
cross join (select distinct product from prices_test) p
) dp
left outer join prices_test pt on pt.price_date = dp.price_date and pt.product = dp.product;
Run Code Online (Sandbox Code Playgroud)
我想我有一个解决方案,使用增量方法来获得 CTE 的最终结果:
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
Run Code Online (Sandbox Code Playgroud)
mindate 检索数据集中可能的最早日期dates 生成从最早日期到今天的日期日历。productdates 交叉连接所有可能的产品和所有可能的日期ranges 确定在每个日期应用的价格日期inner join条件过滤掉没有相关价格日期的日期演示:http : //www.sqlfiddle.com/#!4/ e528f/ 126
| 归档时间: |
|
| 查看次数: |
6216 次 |
| 最近记录: |