Home > Blockchain >  Oracle SQL create records based on DATES
Oracle SQL create records based on DATES

Time:01-11

In desperate need of help from all Oracle SQL guru's. Need to generate output for effective and discontinue dates factoring in 2 other dates namely promo_prep date and promo_start date.

I need to check if promo_prep is greater than eff and less DISC. If it is then become the new disc and the new eff for the next row. Up until the promostart date, so if eff and disc changes happen between promo dates they should remain. Only when promo dates fall between EFF and DISC do they need to be applied and create a new record. Images shown below. Appreaciate any help with this query.

Thank you

Table view before transformation

enter image description here

Desired Ouput

enter image description here

DDL

CREATE TABLE TEST1
( item        varchar2(20),
  loc         varchar2(20),
  qty         number,
  eff         date,
  disc        date,
  promo_prep  date,
  promostart  date
);
--
Insert into TEST1
   (ITEM, LOC, QTY, EFF, DISC, 
    PROMO_PREP, PROMOSTART)
 Values
   ('item1', 'loc1', 280, TO_DATE('11/29/2022', 'MM/DD/YYYY'), TO_DATE('1/10/2023', 'MM/DD/YYYY'), 
    TO_DATE('1/8/2023', 'MM/DD/YYYY'), TO_DATE('1/16/2023', 'MM/DD/YYYY'));
Insert into TEST1
   (ITEM, LOC, QTY, EFF, DISC, 
    PROMO_PREP, PROMOSTART)
 Values
   ('item1', 'loc1', 300, TO_DATE('1/10/2023', 'MM/DD/YYYY'), TO_DATE('1/14/2023', 'MM/DD/YYYY'), 
    TO_DATE('1/8/2023', 'MM/DD/YYYY'), TO_DATE('1/16/2023', 'MM/DD/YYYY'));
Insert into TEST1
   (ITEM, LOC, QTY, EFF, DISC, 
    PROMO_PREP, PROMOSTART)
 Values
   ('item1', 'loc1', 310, TO_DATE('1/14/2023', 'MM/DD/YYYY'), TO_DATE('1/1/2999', 'MM/DD/YYYY'), 
    TO_DATE('1/8/2023', 'MM/DD/YYYY'), TO_DATE('1/16/2023', 'MM/DD/YYYY'));
COMMIT;

CodePudding user response:

You may generate three possible pairs of effective and discontinue dates for each row and then unpivot the result:

with prep as (
  select
    item, loc, qty,
    eff as eff1,
    least(disc, promo_prep) as disc1,
    least(disc, promo_prep) as eff2,
    least(disc, promostart) as disc2,
    least(disc, promostart) as eff3,
    disc as disc3
  from test1
)
select *
from prep
unpivot (
  (eff, disc) for type_ in (
    (eff1, disc1) as 'before_promo',
    (eff2, disc2) as 'promo',
    (eff3, disc3) as 'after_promo'
  )
)
/*Include only valid combin*/
where eff < disc
ITEM LOC QTY TYPE_ EFF DISC
item1 loc1 280 before_promo 2022-11-29 2023-01-08
item1 loc1 280 promo 2023-01-08 2023-01-10
item1 loc1 300 promo 2023-01-08 2023-01-14
item1 loc1 310 promo 2023-01-08 2023-01-16
item1 loc1 310 after_promo 2023-01-16 2999-01-01

See SQL fiddle

CodePudding user response:

You can do this pretty straightforwardly by just appending a row when promo_prep is between the eff and disc dates

select
  item,
  loc,
  qty,
  eff,
  case 
    when promo_prep between eff and disc then promo_prep
    else disc
  end as disc
from test1

union all

select
  item,
  loc,
  qty,
  promo_prep as eff,
  disc
from test1
where 
  promo_prep between eff and disc
  
ITEM LOC QTY EFF DISC
item1 loc1 280 2022-11-29T00:00:00Z 2023-01-08T00:00:00Z
item1 loc1 300 2023-01-10T00:00:00Z 2023-01-14T00:00:00Z
item1 loc1 310 2023-01-14T00:00:00Z 2999-01-01T00:00:00Z
item1 loc1 280 2023-01-08T00:00:00Z 2023-01-10T00:00:00Z

sqlfiddle

  • Related