안녕하세요, 제 설명이 명확하지 않아 재질문드립니다.
Procedure를 활용한 최신데이터만 업데이트 할 때 쿼리 질문드립니다.
log_ymd | id | join_ymd | join_week | col1_yn | col2_yn |
20200101 | AAA | 20191223 | 50 | y | |
20200101 | AAA | 20191223 | 50 | y | |
20200108 | AAA | 20191223 | 50 | y | y |
20200109 | AAA | 20191223 | 50 | y | |
20200101 | BBB | 20180101 | 1 | y | y |
... |
위와 같은 테이블이 있습니다.
만들고자 하는 테이블은 다음과 같습니다.
row_no(FYI) | log_yyyy | log_week | id | join_yyyy | join_week | col1_yn_count | col2_yn_count | week_past | join_week_period |
1 | 2020 | 1 | AAA | 2019 | 50 | 1 | 1 | 25 | 28 |
2 | 2020 | 2 | AAA | 2019 | 50 | 1 | 2 | 24 | 27 |
3 | 2020 | 1 | BBB | 2018 | 1 | 1 | 1 | 25 | 130 |
... | ... | ... |
log_yyyy와 log_week는 log_ymd에서 연도와 주차만 추출합니다. (join_yyyy, join_week도 동일)
id별 log_yyyy, log_week에 따라 주차별 col1_yn의 "Y"값 수를 col1_yn_count로 집계하는게 목적입니다.
여기서 Procedure를 사용하여 주단위로 row를 생성하고 싶습니다.
2번째 테이블(결과)에서 row_no(참고용) 중 2020년 1주차 code run 시 1번과 3번 row 결과가 나오고, 2주차 code run시 2번 row 결과가 나오기를 희망합니다(row 순서 무관), 이 때 procedure를 써서 현재주차(26주)까지 1주씩 업데이트가 되게끔 만들고자 합니다.
이 때 week_past는 현재주차(26주) - log_ymd, week 값을 계산하고, (예: 26-1=25)
join week period는 join_ymd를 써서 가입한 날로부터 이번주차까지의 주차를 계산하고 싶습니다. (예: row=3일 때 52+52+26=130)
한번에 질문이 많아서 정리가 조금 어려운데, 혹시 여전히 답변주시기 어려운 경우 현재주차 기준으로 procedure문을 통해 주차별 집계가 될 수 있는 부분만 답변주시면 큰 도움이 될 것 같습니다.
답변에 미리 감사드립니다.
WITH t AS ( SELECT '20200101' log_ymd, 'AAA' id, '20191223' join_ymd, '50' join_week, 'y' col1_yn, '' col2_yn FROM dual UNION ALL SELECT '20200101', 'AAA', '20191223', '50', '' , 'y' FROM dual UNION ALL SELECT '20200108', 'AAA', '20191223', '50', 'y', 'y' FROM dual UNION ALL SELECT '20200109', 'AAA', '20191223', '50', '' , 'y' FROM dual UNION ALL SELECT '20200101', 'BBB', '20180101', '1' , 'y', 'y' FROM dual ) SELECT TO_CHAR( log_dt + 3, 'yyyy') log_yyyy , (log_dt - sdt) / 7 + 1 log_week , id , TO_CHAR(join_dt + 3, 'yyyy') join_yyyy , (join_dt - join_sdt) / 7 + 1 join_week , COUNT(col1_yn) col1_yn_cnt , COUNT(col2_yn) col2_yn_cnt , (edt - log_dt) / 7 week_past , (edt - join_dt) / 7 join_week_period FROM (SELECT log_ymd, id, join_ymd, join_week, col1_yn, col2_yn , TRUNC(TO_DATE( log_ymd, 'yyyymmdd'), 'iw') log_dt , TRUNC(TO_DATE(join_ymd, 'yyyymmdd'), 'iw') join_dt , TRUNC(TRUNC(TO_DATE(join_ymd, 'yyyymmdd'), 'yy'), 'iw') join_sdt , TRUNC(TRUNC(sysdate, 'yy'), 'iw') sdt , TRUNC(sysdate, 'iw') edt FROM t WHERE log_ymd LIKE TO_CHAR(sysdate, 'yyyy')||'%' ) GROUP BY id, log_dt, join_dt, sdt, edt, join_sdt ORDER BY id, log_dt, join_dt ;
네 52주가 맞는데 잘못된 값이네요. 현재주차는 sysdate 기준으로 뽑았는데 첫주차가 카운트가 안되어서 말씀하신 것 처럼 28주가 되는게 맞는 것 같습니다.
코드 감사드립니다.
1. 이해를 위해 추가질문드리면 yy는 연도추출 (2020년인 경우 20년), iw는 월요일 기준 주차를 쓰는걸로 아는데, sdt와 edt를 TRUNC와 yy, iw를 써서 / 7하게 되면 어떻게 연산이 되는지요?
2. WHERE log_ymd LIKE TO_CHAR(sysdate, 'yyyy')||'%' 문에 대해 설명해주시면 감사하겠습니다.
알려주심에 다시 한번 감사드려요!
1. 연산 과정 설명
TRUNC 는 단위에 맞게 잘라내는 함수입니다.
숫자에 적용하면 TRUNC(11.12, 0) = 11, TRUNC(11.12, 1) = 11.1, TRUNC(11.12, -1) = 10
날짜에도 적용 가능합니다.
TRUNC(sysdate, 'yy') = 2020.01.01 (해당 년 1월 1일)
TRUNC(sysdate, 'iw') = 2020.07.06 (해당 주 월요일)
TRUNC(TRUNC(sysdate, 'yy'), 'iw') = 2019.12.30 (1월1일에 해당하는 주의 월요일)
해당년도 첫주차 월요일을 sdt 로 구했습니다.
log_ymd 해당 주 월요일을 log_dt 로 구했습니다.
두개의 월요일끼리 날짜 차이를 7로 나누면 주차가 나오는 것입니다. 첫주가 1주차가 되기 위해 + 1
2. 조건절 설명 : 해당년도 자료만 가져오기 위한 조건입니다.
WHERE log_ymd LIKE TO_CHAR(sysdate, 'yyyy')||'%'
WHERE log_ymd LIKE '2020'||'%'
WHERE log_ymd LIKE '2020%'