Skip to Main Content

SQL & PL/SQL

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Consuming "shift" time with units of work

John_KApr 3 2018 — edited Apr 4 2018

I have been trying to get my head around this problem for a while now, so thought I'd reach out on here to see if anyone has any pointers! I have a table which holds "shifts" - for each day, a from time and a to time. Between those dates are "working hours"  - i.e. hours available to say, assemble units in a factory.

I also have a table of "units" and the time taken to assembly each. Now what I want to do is overlay the units table with the shifts table, to calculate the point at which each unit will be built according to the shifts. So I might start building a unit, but then there is a lunch break, so I take that off, and then start from where I left off when I return from lunch (this is all possible in real-life). I also (for simplicity) can assume that the very first shift I start on, I start building a new unit. Shifts can vary day to day, but this is reflected in the shifts table.

So let's say I have shifts:

FromTo
01/01/2018 08:0001/01/2018 09:00
01/01/2018 09:1001/01/2018 12:00
01/01/2018 12:3001/01/2018 15:05
01/01/2018 15:1001/01/2018 17:00
02/01/2018 08:0002/01/2018 09:00
02/01/2018 09:1002/01/2018 12:00
02/01/2018 12:3002/01/2018 16:00

and I have these units to build:

UnitTime to Build (Minutes)
145
225
315
455
550
655
755
840
955

Then I want a result set which looks something like this for my units (I'm only really interested in the unit start time):

UnitStart Date/Time
101/01/2018 08:00
201/01/2018 08:45
301/01/2018 09:20
401/01/2018 09:35
501/01/2018 10:30
601/01/2018 11:20
701/01/2018 12:45
801/01/2018 13:40
9

01/01/2018 14:20

So if you look, we jump over the break times, and carry on comsuming time in the next "bucket". I've only done it for the one day above, however the number of units may roll over into the second day and beyond. Obviously there might be more units than time, and vice versa - I'm not interested in the blanks - just the time that I'm actually building units.

I started by bucketing the shifts into durations, but I was having difficulty working out how to consume part of a unit in one bucket, and the remainder in the other bucket.

with shifts as (

  select to_date('01012018 08:00', 'ddmmyyyy hh24:mi') from_dt, to_date('01012018 09:00', 'ddmmyyyy hh24:mi') to_dt from dual union all

  select to_date('01012018 09:10', 'ddmmyyyy hh24:mi') from_dt, to_date('01012018 12:00', 'ddmmyyyy hh24:mi') to_dt from dual union all

  select to_date('01012018 12:30', 'ddmmyyyy hh24:mi') from_dt, to_date('01012018 15:05', 'ddmmyyyy hh24:mi') to_dt from dual union all

  select to_date('01012018 15:10', 'ddmmyyyy hh24:mi') from_dt, to_date('01012018 17:00', 'ddmmyyyy hh24:mi') to_dt from dual union all

  select to_date('02012018 08:00', 'ddmmyyyy hh24:mi') from_dt, to_date('02012018 09:00', 'ddmmyyyy hh24:mi') to_dt from dual union all

  select to_date('02012018 09:10', 'ddmmyyyy hh24:mi') from_dt, to_date('02012018 12:00', 'ddmmyyyy hh24:mi') to_dt from dual union all

  select to_date('02012018 12:30', 'ddmmyyyy hh24:mi') from_dt, to_date('02012018 16:00', 'ddmmyyyy hh24:mi') to_dt from dual  

),

work_units as (

  select 1 unit_id, numtodsinterval(45,'Minute') from dual union all

  select 2 unit_id, numtodsinterval(25,'Minute') from dual union all

  select 3 unit_id, numtodsinterval(15,'Minute') from dual union all

  select 4 unit_id, numtodsinterval(55,'Minute') from dual union all

  select 5 unit_id, numtodsinterval(50,'Minute') from dual union all

  select 6 unit_id, numtodsinterval(55,'Minute') from dual union all

  select 7 unit_id, numtodsinterval(55,'Minute') from dual union all

  select 8 unit_id, numtodsinterval(40,'Minute') from dual union all

  select 9 unit_id, numtodsinterval(55,'Minute') from dual

)

select v.from_dt, v.to_dt, nvl(lag(v.r_ttl) over (order by v.from_dt),0) bucket_from, v.r_ttl bucket_to from (

  select s.from_dt, s.to_dt,

         s.to_dt - s.from_dt shift_dur,

         sum(s.to_dt - s.from_dt) over (order by s.from_dt) r_ttl

  from shifts s) v order by v.from_dt

Any pointers would be great

This post has been answered by John_K on Apr 3 2018
Jump to Answer
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on May 2 2018
Added on Apr 3 2018
8 comments
917 views