我有一个数据集:
type month id1 id2 id3 value
history jan-17 1 2 3 10
future jan-17 1 2 3 15
history feb 1 2 3 12
history march 1 2 3 11
future march 1 2 3 14
我希望根据一些计算并基于type
列的值来获得每个月的价值。
例如:输出应如下所示:
month id1 id2 id3 value
JAN-17 1 2 3 15(future value of jan) + 0(as future value of feb is not present)+ 14(take the future value of march)
FEB-17 1 2 3 10(history value of jan)+14(take the future value of march)
MAR-17 1 2 3 10(history value of jan)+12(history value of feb)+11(history value of mar)
计算基于一年中每个月的季度数。 如果是一个季度的第一个月,则采用第一个月的未来值+第二个月的未来+第三个月的未来值
如果月份是一季度的第2个月,则取第1个月的历史值+第2个月的未来值+第3个月的未来值
如果月份是一个季度的第3个月,则取第1个月的历史值+第2个月的历史值+第3个月的未来值。
我已经尝试基于月id1
,id2
,id3
对数据集进行分区,但它没有给我预期的结果。
您想要的输出与您进一步编写的规则相矛盾:
如果是一个季度的第一个月,则采用第一个月的未来值+第二个月的未来+第三个月的未来值
如果月份是一季度的第2个月,则取第1个月的历史值+第2个月的未来值+第3个月的未来值
如果月份是一个季度的第3个月,则取第1个月的历史值+第2个月的历史值+第3个月的未来值
我实现了这些规则,因为它们具有更清晰的逻辑并且更容易实现:
with t1 as (select 'history' type from dual union all select 'future' type from dual),
d as (select add_months(date '2017-01-01', rownum - 1) month, 1 id1, 2 id2, 3 id3 from dual connect by level < 4),
t2 as (select * from t1, d),
source (type, month, id1, id2, id3, value) as (
select 'history', 'jan-17', 1, 2, 3, 10 from dual union all
select 'future', 'jan-17', 1, 2, 3, 15 from dual union all
select 'history', 'feb-17', 1, 2, 3, 12 from dual union all
select 'history', 'mar-17', 1, 2, 3, 11 from dual union all
select 'future', 'mar-17', 1, 2, 3, 14 from dual)
select to_char(month, 'mon-yy') mon, id1, id2, id3, history, future,
sum(history) over (partition by to_char(month, 'Q') order by month) - history +
sum(future) over (partition by to_char(month, 'Q') order by month desc) value
from (select t2.type, t2.month, nvl(s.id1, t2.id1) id1, nvl(s.id2, t2.id2) id2, nvl(s.id3, t2.id3) id3, nvl(value, 0) value
from t2 left join source s on s.type = t2.type and s.month = to_char(t2.month, 'mon-yy'))
pivot (sum(value) for type in ('history' history, 'future' future))
order by month
这个怎么运作:
t1
,t2
和d
用于生成月份和类型的完整列表MON ID1 ID2 ID3 HISTORY FUTURE VALUE
------------ ---------- ---------- ---------- ---------- ---------- ----------
jan-17 1 2 3 10 15 29
feb-17 1 2 3 12 0 24
mar-17 1 2 3 11 14 36
该解决方案可以应用于任何时间段,将分别计算每个季度的数据。
我不知道如何处理id1,id2,id3所以我选择忽略它,更好地解释它的相应逻辑。对于历史,特定月份的未来,它是否总是相同的价值?
with
x as
(select 'hist' type, To_Date('JAN-2017','MON-YYYY') ym , 10 value from dual union all
select 'future' type, To_Date('JAN-2017','MON-YYYY'), 15 value from dual union all
select 'future' type, To_Date('FEB-2017','MON-YYYY'), 1 value from dual),
y as
(select * from x Pivot(Sum(Value) For Type in ('hist' as h,'future' as f))),
/* Pivot for easy lag,lead query instead of working with rows..*/
z as
(
select ym,sum(h) H,sum(f) F from (
Select y.ym,y.H,y.F from y
union all
select add_months(to_Date('01-JAN-2017','DD-MON-YYYY'),rownum-1) ym, 0 H, 0 F
from dual connect by rownum <=3 /* depends on how many months you are querying...
so this dual adds the corresponding missing 0 records...*/
) group by ym
)
select
ym,
Case
When MOD(Extract(Month from YM),3) = 1
Then F + Lead(F,1) Over(Order by ym) + Lead(F,2) Over(Order by ym)
When MOD(Extract(Month from YM),3) = 2
Then Lag(H,1) Over(Order by ym) + F + Lead(F,1) Over(Order by ym)
When MOD(Extract(Month from YM),3) = 3
Then Lag(H,2) Over(Order by ym) + Lag(H,1) Over(Order by ym) + F
End Required_Value
from z