Reputation: 31
This is the input Table
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
This is the output required.(Expected date,late/early,gap based on conditions mentioned)
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
Upvotes: 0
Views: 178
Reputation:
Here is a solution using the match_recognize
clause, introduced in Oracle 12.1.
Test data:
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, 'aa', 'D1', 'dd', to_date('07-06-2020'), 30 from dual union all
select 1, 'aa', 'D1', 'dd', to_date('12-07-2020'), 30 from dual union all
select 1, 'aa', 'D1', 'dd', to_date('09-08-2020'), 30 from dual union all
select 1, 'aa', 'D1', 'dd', to_date('07-09-2020'), 28 from dual union all
select 1, 'aa', 'D1', 'dd', to_date('11-10-2020'), 28 from dual union all
select 1, 'aa', 'D1', 'dd', 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, 'bb', 'D2', 'cd', to_date('06-01-2020'), 10 from dual
;
Query:
with
prep (id, name, disease, drug, ship_date, supply, e_date, cls, exp_date) as (
select id, name, disease, drug, ship_date, supply, e_date, cls,
case cls when 'A' then lag(e_date + supply)
over (partition by id, disease, drug
order by ship_date)
else e_date end as exp_date
from input_table
match_recognize(
partition by id, disease, 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, name, disease, drug, ship_date, supply, 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, disease, drug, ship_date
;
Output:
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
Upvotes: 3