휴일테이블 : 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