问题描述
这是输入表
id name disease drug ship date supply
1 aa D1 dd 10-05-2020 30
1 aa D1 dd 07-06-2020 30
1 aa D1 dd 12-07-2020 30
1 aa D1 dd 09-08-2020 30
1 aa D1 dd 07-09-2020 28
1 aa D1 dd 11-10-2020 28
1 aa D1 dd 10-11-2020 28
2 bb D2 cd 01-01-2020 10
2 bb D2 cd 06-01-2020 10
这是所需的输出。(预期日期,晚/早,基于提到的条件的差距)
id name disease drug ship date supply expected date late/early Gap
1 aa D1 dd 10-05-2020 30 null first order 0
1 aa D1 dd 07-06-2020 30 09-06-2020 early 0
1 aa D1 dd 12-07-2020 30 09-07-2020 late 3
1 aa D1 dd 09-08-2020 30 11-08-2020 early 0
1 aa D1 dd 07-09-2020 28 08-09-2020 early 0
1 aa D1 dd 11-10-2020 28 6-10-2020 late 5
1 aa D1 dd 10-11-2020 28 08-11-2020 late 2
2 bb D2 cd 01-01-2020 10 null first order 0
2 bb D2 cd 06-01-2020 10 11-01-2020 early 5
- id、name、disease、drug、shipdate、supply 是给定的字段
- 第一个订单日期是 10-05-2020,如果我们添加 supply(30) 我们得到我们的下一个预期日期,即 09-06-2020(我已经在下一行显示了它来计算差距)但是病人已经完成了他的07-06-2020 的第二个订单比预期早(所以它是提前补货,因此差距为 0),在这种情况下,下一个预期日期是前一个预期日期(09-06-2020)+供应(30),即 09 -07-2020。
- 他第三次订购是在 12-07-2020 延迟了 3 天,所以补货晚了,在这种情况下,下一个预计日期是发货日期(12-07-2020)+供应(30 ) 即 11-08-2020。
- 简而言之,如果是提前补货,那么下一个预期日期是前一个预期日期 + 供应量,如果是延迟补货,则是发货日期 + 供应量。
- 注意:- 主要目的是计算差距。
解决方法
这是使用 match_recognize
子句的解决方案,在 Oracle 12.1 中引入。
测试数据:
alter session set nls_date_format = 'dd-mm-yyyy';
create table input_table(id,name,disease,drug,ship_date,supply) as
select 1,'aa','D1','dd',to_date('10-05-2020'),30 from dual union all
select 1,to_date('07-06-2020'),to_date('12-07-2020'),to_date('09-08-2020'),to_date('07-09-2020'),28 from dual union all
select 1,to_date('11-10-2020'),to_date('10-11-2020'),28 from dual union all
select 2,'bb','D2','cd',to_date('01-01-2020'),10 from dual union all
select 2,to_date('06-01-2020'),10 from dual
;
查询:
with
prep (id,supply,e_date,cls,exp_date) as (
select id,case cls when 'A' then lag(e_date + supply)
over (partition by id,drug
order by ship_date)
else e_date end as exp_date
from input_table
match_recognize(
partition by id,drug
order by ship_date
measures a.ship_date + sum(supply) - supply as e_date,classifier() as cls
all rows per match
pattern (a b*)
define b as ship_date <= a.ship_date + sum(supply) - supply
)
)
select id,exp_date,case when exp_date is null then 'first order'
when cls = 'A' then 'late'
else 'early' end as late_or_early,case cls when 'A' then ship_date - exp_date end as gap
from prep
order by id,ship_date
;
输出:
ID NAME DISEASE DRUG SHIP_DATE SUPPLY EXP_DATE LATE_OR_EARLY GAP
-- ---- ------- ---- ---------- ---------- ---------- ------------- ---
1 aa D1 dd 10-05-2020 30 first order
1 aa D1 dd 07-06-2020 30 09-06-2020 early
1 aa D1 dd 12-07-2020 30 09-07-2020 late 3
1 aa D1 dd 09-08-2020 30 11-08-2020 early
1 aa D1 dd 07-09-2020 28 10-09-2020 early
1 aa D1 dd 11-10-2020 28 08-10-2020 late 3
1 aa D1 dd 10-11-2020 28 08-11-2020 late 2
2 bb D2 cd 01-01-2020 10 first order
2 bb D2 cd 06-01-2020 10 11-01-2020 early