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 일 출력
감사합니다!
정말 감사합니다. CONNECT BY LEVEL 관련 다른 글에 마농님께서 단일 행에만 써야한다는 걸 본 것같은데 저런 이야기 였군요. 하나하나 자세하게 설명해주셔서 정말 감사합니다!.
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 하는 방법도 있을것 같은데....@.@
옙...^^
행이 하나씩 늘때마다 수행시간은 기하급수로 늘어납니다.
절대로 이렇게 사용해서는 안됩니다.
답변갑사합니다!!
select a.*, 1 lv
from t a
union all
select a.*, 2 lv
from t a, t b
union all
select a.*, 3 lv
from t a, t b, t c
union all
..
이런 식으로 셀프 조인하면서 데이터가 늘어납니다.
그래서 테이블 자체에 connect by level 하시면 안 되는 거예요.
테이블이 크면 cpu, 메모리가..
아 그렇군요 설명 감사드립니다!