I have a table with phone nos , complaint booked date,complaint cleared date.
Need to find the time taken to clear the complaint in Hours, excluding the after working hours and holidays.
The working hours is 8:00 A.M to 6:00 P.M. After working hours 6.00 P.M to nextday 8:00 A.M.
Assume 14/01/2013 as holiday.
Sample data
CREATE TABLE "FAULTS"
( "PHONE_NO" VARCHAR2(20 BYTE),
"COMP_BOOKD_DATE" DATE,
"COMP_CLEARED_DATE" DATE,
)
1. INSERT INTO FAULTS (PHONE_NO, COMP_BOOKD_DATE, COMP_CLEARED_DATE) VALUES ('xxx-yyyyyy', TO_DATE('06/01/2013 18:17:52', 'DD/MM/YYYY HH24:MI:SS'), TO_DATE('08/01/2013 16:31:21', 'DD/MM/YYYY HH24:MI:SS'))
2. INSERT INTO FAULTS (PHONE_NO, COMP_BOOKD_DATE, COMP_CLEARED_DATE) VALUES ('xxx-zzzzzz', TO_DATE('13/01/2013 12:30:52', 'DD/MM/YYYY HH24:MI:SS'), TO_DATE('15/01/2013 16:31:21', 'DD/MM/YYYY HH24:MI:SS'))
NOTE: edited on 17-jan-2013 to correct a few bugs I discovered...
I'll give you the bits and pieces for this, you'll put them together.
Note: I didn't test all of the edge conditions - consider this rough psuedo code, I'm giving you an approach here. You'll have to read it, understand it, verify it does what you need, test it!!! (please)
my approach:
a) figure out the number of FULL business days between the two dates. We'll multiply that by 10 hours to get that number hours.
b) look at comp_bookd_date and figure out if it contributes any hours, if so, compute them
c) same for comp cleared date, if the day is not a weekend/holiday and is on a different day from comp_bookd_date (no ED on bookED - I cannot tell you how many times I typed that wrong :) ) - compute the hours it contributes.
Here is a stab at it:
ops$tkyte%ORA11GR2> create table holidays( dt date );
Table created.
ops$tkyte%ORA11GR2> insert into holidays values (to_date( '25-jan-2013', 'dd-mon-yyyy' ) );
1 row created.
ops$tkyte%ORA11GR2> commit;
Commit complete.
ops$tkyte%ORA11GR2>
ops$tkyte%ORA11GR2>
ops$tkyte%ORA11GR2> drop table faults;
Table dropped.
ops$tkyte%ORA11GR2>
ops$tkyte%ORA11GR2> CREATE TABLE "FAULTS"
2 ( "PHONE_NO" VARCHAR2(20 BYTE),
3 "COMP_BOOKD_DATE" DATE,
4 "COMP_CLEARED_DATE" DATE
5 )
6 /
Table created.
ops$tkyte%ORA11GR2> INSERT INTO FAULTS (PHONE_NO, COMP_BOOKD_DATE, COMP_CLEARED_DATE) VALUES
2 ('xxx-yyyyyy', TO_DATE('06/01/2013 18:17:52', 'DD/MM/YYYY HH24:MI:SS'),
3 TO_DATE('08/01/2013 16:31:21', 'DD/MM/YYYY HH24:MI:SS'));
1 row created.
ops$tkyte%ORA11GR2>
ops$tkyte%ORA11GR2> INSERT INTO FAULTS (PHONE_NO, COMP_BOOKD_DATE, COMP_CLEARED_DATE) VALUES
2 ('xxx-zzzzzz', TO_DATE('13/01/2013 12:30:52', 'DD/MM/YYYY HH24:MI:SS'),
3 TO_DATE('15/01/2013 16:31:21', 'DD/MM/YYYY HH24:MI:SS'));
1 row created.
ops$tkyte%ORA11GR2> INSERT INTO FAULTS (PHONE_NO, COMP_BOOKD_DATE, COMP_CLEARED_DATE) VALUES
2 ('xxx-xxxx', TO_DATE('23/01/2013 12:30:52', 'DD/MM/YYYY HH24:MI:SS'),
3 TO_DATE('30/01/2013 16:31:21', 'DD/MM/YYYY HH24:MI:SS'));
1 row created.
ops$tkyte%ORA11GR2>
ops$tkyte%ORA11GR2> INSERT INTO FAULTS (PHONE_NO, COMP_BOOKD_DATE, COMP_CLEARED_DATE)
2 VALUES ('xxx-Ayrayyyy', TO_DATE('07/01/2013 03:17:52', 'DD/MM/YYYY HH24:MI:SS'),
3 TO_DATE('07/01/2013 06:31:21', 'DD/MM/YYYY HH24:MI:SS'))
4 /
1 row created.
I added a new row that hits weekends and a holiday....
ops$tkyte%ORA11GR2> select phone_no, comp_bookd_date, comp_cleared_date,
2 cnt2*10 + xx+yy tot_hours
3 from (
4 select phone_no, comp_bookd_date, comp_cleared_date,
5 (select count(*)
6 from dual
7 where to_char(comp_bookd_date+level,'dy') not in ('sat','sun')
8 start with trunc(comp_cleared_date) - trunc( comp_bookd_date ) > 1
9 connect by level <= trunc(comp_cleared_date)-trunc(comp_bookd_date)-1 )
10 - (select count(*)
11 from holidays
12 where dt between trunc(comp_bookd_date)+1 and trunc(comp_cleared_date)-1) cnt2,
13 case when to_number( to_char( comp_bookd_date, 'hh24mi' ) ) >= 1800
14 then 0
15 when to_char( comp_bookd_date, 'dy' ) in ( 'sat', 'sun' ) or exists (select null from holidays where dt = trunc(comp_bookd_date))
16 then 0
17 when trunc(comp_bookd_date) = trunc(comp_cleared_date)
18 then
19 case when to_char(comp_cleared_date,'hh24') < '08'
20 then 0
21 else to_date( to_char( least( 1800, to_number(to_char(comp_cleared_date, 'hh24mi')) ), 'fm0000' ), 'hh24mi' )
22 -to_date( to_char( greatest( 0800, to_number(to_char(comp_bookd_date,'hh24mi')) ), 'fm0000' ), 'hh24mi' )
23 end
24 else
25 case when to_char(comp_bookd_date,'hh24') >= '18'
26 then 0
27 else to_date( '1800', 'hh24mi' )
28 -to_date( to_char( greatest( 0800, to_number(to_char(comp_bookd_date,'hh24mi')) ), 'fm0000' ), 'hh24mi' )
29 end
30 end *24 xx,
31 case when trunc(comp_bookd_date) = trunc(comp_cleared_date)
32 then 0
33 when to_char( comp_cleared_date, 'dy' ) in ( 'sat', 'sun' ) or exists (select null from holidays where dt = trunc(comp_cleared_date))
34 then 0
35 when to_number( to_char( comp_cleared_date, 'hh24mi' ) ) <= 800
36 then 0
37 when to_char( comp_cleared_date, 'hh24' ) >= '18'
38 then 10
39 else comp_cleared_date - (trunc(comp_cleared_date)+8/24)
40 end *24 yy
41 from faults
42 )
43 /
PHONE_NO COMP_BOOKD_DATE COMP_CLEARED_DATE TOT_HOURS
-------------------- ------------------------ ------------------------ ----------
xxx-yyyyyy sun 06-jan-2013 18:17:52 tue 08-jan-2013 16:31:21 18.5225
xxx-zzzzzz sun 13-jan-2013 12:30:52 tue 15-jan-2013 16:31:21 18.5225
xxx-xxxx wed 23-jan-2013 12:30:52 wed 30-jan-2013 16:31:21 44.0225
xxx-Ayrayyyy mon 07-jan-2013 03:17:52 mon 07-jan-2013 06:31:21 0
Ok, so lines 5-9 compute the number of non-weekend days between the day after the bookd date but before the cleared date are not weekends.
Lines 10 through 12 compute the number of holidays in that same period of time.
We subtract the holidays out and you can then multiply that by ten to get the number of hours for that.
then, we look at comp_bookd_date.
If you inserted this after 6pm, we add no extra hours.
If you inserted this on a weekend or holiday, we add no extra hours.
If you booked this and cleared it on the same day - we need to compute the hours in between bookd and cleared after taking bookd up to at least 8am and setting cleared back to at least 6pm. If we cleared this before 8am - we return 0, else we do the math rounding bookd up to 8am and cleared back to 6pm
If you booked and cleared on different days - we just need to figure the hours between at least 8am or booked time, which ever is greatest and 6pm - unless we bookd this after 6pm!
We multiply that by 24 and you get the number of hours to add to the previous computation.
then we look at comp_cleared_date.
if you booked and cleared on the same day, we add no extra hours
if you cleared on a weekend or holiday, we add no extra hours
if you cleared early in the morning, before 8am, no extra hours
if you cleared after 6pm - just return 10
else - return the number of hours since 8am of that day...
Now you need to test it comprehensively - making sure it hits all of the boundary conditions :) I think it does - but I wrote this pretty quick - I might have missed a case...