by 마카히로 [Oracle 기초] oracle 날짜 두사이 불러오기 [2023.01.25 19:13:20]
안녕하세요
시작일과 종료일이 있는 테이블에서 시작일과 종료일 사이 날짜를 행으로 불러오는 쿼리를 찾아서 적용하였는데 잘 안되서 질문드립니다!
시작일 | 종료일 | |
1 | 2023-01-01 | 2023-01-05 |
2 | 2023-01-02 | 2023-01-04 |
~ | ~ | ~ |
n번째 | 2023-01-25 | 2023-01-25 |
WITH TEST1 AS (생략) SELECT TO_CHAR(TO_DATE(시작일) +LEVEL -1, 'YYYY-MM-DD') AS DATE FROM TEST1 CONNECT BY LEVEL <= (TO_DATE(종료일,'YYYYMMDD') - TO_DATE(시작일,'YYYYMMDD') +1)
이렇게 짤 경우, 시작일과 종료일 사이에 날짜들만 쭉 나와야하는데
생각보다 너무 많은 데이터가 나옵니다 ㅜㅜ
데이터가 왜 많이나오는지 알기 위해 CONNECT BY LEVEL <= 2 를 넣었더니
N* (N+1) 개 데이터가 나오더라구요 ㅜㅜ
고수님들 도움 간곡히 부탁드립니다!
CONNECT BY LEVEL <= n 형태의 행복제 방식은
dual 처럼 1행의 자료에만 적용하는 방법입니다.
여러행의 자료에 직접 적용하면 기하급수로 복제가 됩니다.
http://gurubee.net/article/55635
WITH test1 AS ( SELECT 1 no, '2023-01-01' sdt, '2023-01-05' edt FROM dual UNION ALL SELECT 2, '2023-01-02', '2023-01-04' FROM dual UNION ALL SELECT 3, '2023-01-25', '2023-01-25' FROM dual ) SELECT no , TO_CHAR(sdt + lv - 1, 'yyyy-mm-dd') dt FROM (SELECT no , TO_DATE(sdt, 'yyyy-mm-dd') sdt , TO_DATE(edt, 'yyyy-mm-dd') edt FROM test1 ) , (SELECT LEVEL lv FROM dual CONNECT BY LEVEL <= 99) WHERE lv <= edt - sdt + 1 ORDER BY no, dt ;
제가 어려웠던 부분 공유드리고자합니다^^;;
sdt 2023-01-01 ,edt 2023-01-03 일때
조정값1 select : sdt + lv
조정값2: where : lv <=edt -sdt
1. 시작일,종료일을 포함하고 싶을 때
조정값1:sdt + lv -1
조정값2:lv<= edt-sdt +1
>결과: 1/1,1/2,1/3일 출력
2. 시작일 제외, 종료일을 포함하고 싶을 때
조정값1: sdt + lv
조정값2: edt-sdt
>결과: 1/2,1/3 일 출력
3.시작일 포함, 종료일 제외하고 싶을 때
조정값1: sdt + lv-1
조정값2: edt-sdt
>결과: 1/1,1/2 일 출력
WITH TMP (NO, SDT, EDT) AS ( SELECT 1, '2023-01-01', '2023-01-05' FROM DUAL UNION ALL SELECT 2, '2023-01-02', '2023-01-04' FROM DUAL UNION ALL SELECT 3, '2023-01-25', '2023-01-25' FROM DUAL ) SELECT DISTINCT NO, TO_CHAR(TO_DATE(SDT, 'YYYY-MM-DD') + LEVEL -1, 'YYYY-MM-DD') AS DT FROM TMP CONNECT BY LEVEL <= (TO_DATE(EDT,'YYYY-MM-DD') - TO_DATE(SDT, 'YYYY-MM-DD') +1) ORDER BY NO, DT;
이렇게 하면 되긴 하는데..마농님 말씀 처럼 기하급수로 복제가 되서 Row가 많을시에는 어떻게 될지 모르겠네요..
그룹별 (NO별) CONNECT BY 하는 방법도 있을것 같은데....@.@