ORACLE中的数据密集化,仅使用视图

时间:2016-10-07 18:25:59

标签: oracle

我正在处理观点。在一个我有购买订单的付款条款(30天,2天30天(30/60)等)和其他东西:

PO    SUPPLIER    DELIVERY_DATE PAYMENT_TERMS
1     A           2016-11-10    30 DAYS
2     B           2016-11-10    30/60 DAYS

我想制作一个包含付款时间表的视图。 由于许可,我不能使用表格,只有视图和我因此而遇到很多麻烦(尝试物化视图进行更新,没有运气,因为ORACLE抛出查询是复杂的)。

这就是我想要的:

PO    SUPPLIER    DELIVERY_DATE PAYMENT_TERMS PAYMENT_DATE AMOUNT
1     A           2016-11-10    30 DAYS       2016-12-10   100%
2     B           2016-11-10    30/60 DAYS    2016-12-10   50%
2     B           2016-11-10    30/60 DAYS    2017-01-10   50%

任何提示?

谢谢!

2 个答案:

答案 0 :(得分:1)

好吧,您似乎需要确定Payment_Terms的每个不同值的真正含义,因为没有内置规则将“30/60 DAYS”解释为“一次付款50% 30天后,60天后第二次支付50%“。所以,我理解为什么查询对于具有自动更新的物化视图来说太复杂了。具体来说,需要在输出中为单行输入创建多行通常需要相对复杂的逻辑(使用UNION,花式JOIN语句等)。

你仍然可以使用物化视图,但是你需要自己强制刷新它(定期或者必要时使用触发器)。

无论哪种方式,获得所需内容的查询(其中之一)可能如下所示:

-- build the records for 30 DAYS
select po, supplier, delivery_date, payment_terms, (delivery_date + 30) as payment_date, 100 as amount
from The_Table
where payment_terms = '30 DAYS'
union all
-- build the records for the FIRST payment for 30/60
select po, supplier, delivery_date, payment_terms, (delivery_date + 30) as payment_date, 50 as amount
from The_Table
where payment_terms = '30/60 DAYS'
union all
-- build the records for the SECOND payment for 30/60
select po, supplier, delivery_date, payment_terms, (delivery_date + 60) as payment_date, 50 as amount
from The_Table
where payment_terms = '30/60 DAYS'

希望这有帮助。

答案 1 :(得分:0)

下面的解决方案假设“30”是表示“月”的传统方式 - 所有计算都基于月而不是天。相反,“天”字面意思是,解决方案可以很容易地适应。我假设“payment_terms”sting总是以您呈现的格式(两种可能性中的一种)完全正确,并且第二个数字(如果存在)是第一个数字的精确倍数。我又添加了两个测试行。我想不出有什么理由不能将其变成快速可刷新的物化视图。 (不确定FOR UPDATE - 你想通过这个视图更新什么?)

注意 - 如果最后一列中的百分比是用于进一步的计算,则不应将它们组成字符串(以%符号结尾);相反,它们应该是数字,如1.0000或0.3333或0.5000。

with
     inputs ( po, supplier, delivery_date, payment_terms ) as (
       select 1, 'A', date '2016-11-10', '30 DAYS'     from dual union all
       select 2, 'B', date '2016-11-10', '30/60 DAYS'  from dual union all
       select 3, 'C', date '2015-03-13', '90 DAYS'     from dual union all
       select 4, 'D', date '2015-10-01', '90/270 DAYS' from dual
     ),
     prep ( po, supplier, delivery_date, payment_terms, freq, num ) as (
       select po, supplier, delivery_date, payment_terms,
              to_number(regexp_substr(payment_terms, '\d+', 1, 1)) / 30,
              nvl(to_number(regexp_substr(payment_terms, '\d+', 1, 2)) /
                    to_number(regexp_substr(payment_terms, '\d+', 1, 1)),  1)
       from inputs
     )
select po, supplier, delivery_date, payment_terms,
       add_months ( delivery_date, freq * level ) as payment_date,
       to_char(100/num, '999.99') || '%' as payment_amount
from prep
connect by level <= num
       and prior po = po
       and prior sys_guid() is not null
order by po, payment_date
;


        PO S DELIVERY_DATE PAYMENT_TERMS PAYMENT_DATE PAYMENT_AMOUNT
---------- - ------------- ------------- ------------ --------------
         1 A 10-NOV-2016   30 DAYS       10-DEC-2016   100.00%
         2 B 10-NOV-2016   30/60 DAYS    10-DEC-2016    50.00%
         2 B 10-NOV-2016   30/60 DAYS    10-JAN-2017    50.00%
         3 C 13-MAR-2015   90 DAYS       13-JUN-2015   100.00%
         4 D 01-OCT-2015   90/270 DAYS   01-JAN-2016    33.33%
         4 D 01-OCT-2015   90/270 DAYS   01-APR-2016    33.33%
         4 D 01-OCT-2015   90/270 DAYS   01-JUL-2016    33.33%