휴일테이블 : WORK |
||
사번 | 휴일시작일 | 휴일종료일 |
EMPNO | SDAY | EDAY |
1111 | 2014-04-01 | 2014-04-03 |
1111 | 2014-04-11 | 2014-04-14 |
2222 | 2014-04-23 | 2014-04-28 |
단체휴일정보 테이블 : HOLIDAY | ||
휴일 | ||
HDAY | ||
2014-04-25 |
사번 | 휴일정보 | ||||
1111 | 2014-04-01 | ||||
1111 | 2014-04-02 | ||||
1111 | 2014-04-03 | ||||
1111 | 2014-04-11 | ||||
1111 | 2014-04-14 | << 토요일, 일요일을 제외한 기간이 날짜로 표시 | |||
2222 | 2014-04-23 | ||||
2222 | 2014-04-24 | ||||
2222 | 2014-04-28 | << 토요일, 일요일, 회사단체휴일을 제외한 날짜가 표시 |
WITH TT(EMPNO, SDAY, EDAY) AS ( SELECT '1111', '20140401', '20140403' FROM DUAL UNION ALL SELECT '1111', '20140411', '20140414' FROM DUAL UNION ALL SELECT '2222', '20140423', '20140428' FROM DUAL ) , HOL(HDAY) AS ( SELECT '20140412' FROM DUAL UNION ALL SELECT '20140413' FROM DUAL UNION ALL SELECT '20140425' FROM DUAL UNION ALL SELECT '20140426' FROM DUAL UNION ALL SELECT '20140427' FROM DUAL ) --4. 휴일 제외 하기 SELECT TT.* FROM (--3. 사원별 모든 휴무일 구하기 SELECT TT.EMPNO, TO_CHAR(TO_DATE(TT.SDAY, 'YYYYMMDD') + B.LV - 1, 'YYYYMMDD') HOLDAY FROM (--2. 각 사원별 휴무일 구하기 SELECT EMPNO, SDAY, EDAY, TO_DATE(EDAY, 'YYYYMMDD') - TO_DATE(SDAY, 'YYYYMMDD') + 1 AS DCNT FROM TT ) TT , (--1. 먼저 자료를 복제 하기 위해서 가장먼저 수행. SELECT LEVEL LV FROM ( SELECT MAX(TO_DATE(EDAY, 'YYYYMMDD') - TO_DATE(SDAY, 'YYYYMMDD')) + 1 AS MAX_CNT FROM TT ) B CONNECT BY LEVEL <= B.MAX_CNT ) B WHERE TT.DCNT >= B.LV ORDER BY 1, 2 ) TT , HOL WHERE TT.HOLDAY = HOL.HDAY(+) AND HOL.HDAY IS NULL ORDER BY EMPNO, TT.HOLDAY ;
WITH work (empno, sday, eday) AS ( SELECT '1111', '20140401', '20140403' FROM DUAL UNION ALL SELECT '1111', '20140411', '20140414' FROM DUAL UNION ALL SELECT '2222', '20140423', '20140428' FROM DUAL ) , holiday (hday) AS ( SELECT '20140412' FROM DUAL UNION ALL SELECT '20140413' FROM DUAL UNION ALL SELECT '20140425' FROM DUAL UNION ALL SELECT '20140426' FROM DUAL UNION ALL SELECT '20140427' FROM DUAL ) SELECT empno , TO_DATE ( sday, 'YYYYMMDD' ) + lv - 1 , eday , lv FROM work a , ( SELECT LEVEL lv FROM DUAL CONNECT BY LEVEL <= ( SELECT MAX ( TO_DATE ( eday ) - TO_DATE ( sday ) ) + 1 FROM work ) ) b WHERE TO_DATE ( sday, 'YYYYMMDD' ) + lv - 1 <= TO_DATE ( eday, 'YYYYMMDD' ) AND NOT EXISTS ( SELECT 'X' FROM holiday WHERE TO_DATE ( a.sday, 'YYYYMMDD' ) + lv - 1 = hday ) ORDER BY 1, 2
with t as ( select 1111 empno,'2014-04-01' sday,'2014-04-03' EDAY from dual union all select 1111,'2014-04-11','2014-04-14' from dual union all select 2222,'2014-04-23','2014-04-28' from dual ),h as (select '2014-04-25' hol from dual) select empno,lv from t, (select (to_date('2014-04-01','yyyy-mm-dd') -1 ) + level lv from dual connect by level < (to_date('2014-04-28','yyyy-mm-dd') - to_date('2014-04-01','yyyy-mm-dd')) +2) aa where lv between sday and eday and not exists (select 1 from h where aa.lv = h.hol) and to_char(lv,'d') not in ('1','7') order by empno, sday, lv