안녕하세요. 쿼리 구현에 관해 궁금한 부분이 있어 질문드립니다.
위에서 AMT 컬럼까지가 기초데이터고 뒤에 CAL_AMT가 제가 원하는 결과값인데요.
SELECT 'B1210001' AS PSN_NO, '201401' AS CLYM, 1000 AS AMT , 0 AS CAL_AMT FROM DUAL UNION ALL SELECT 'B1210001' AS PSN_NO, '201402' AS CLYM, -3000 AS AMT , -3000 AS CAL_AMT FROM DUAL UNION ALL SELECT 'B1210001' AS PSN_NO, '201405' AS CLYM, 5000 AS AMT , 0 AS CAL_AMT FROM DUAL UNION ALL SELECT 'B2010001' AS PSN_NO, '201407' AS CLYM, -4000 AS AMT , -4000 AS CAL_AMT FROM DUAL UNION ALL SELECT 'C2710001' AS PSN_NO, '201402' AS CLYM, -5000 AS AMT , -5000 AS CAL_AMT FROM DUAL UNION ALL SELECT 'C2710001' AS PSN_NO, '201403' AS CLYM, 1000 AS AMT , -4000 AS CAL_AMT FROM DUAL UNION ALL SELECT 'C2710001' AS PSN_NO, '201404' AS CLYM, 7000 AS AMT , 0 AS CAL_AMT FROM DUAL
기본적으로 PSN_NO(개인번호) , CLYM(마감년월)별 누계를 구하려고 하는데,
단순하게 개인번호별 당월과 전월만 더하면 LAG함수를 쓰면 되지만 제가 구해야 하는 결과치는 조금 다릅니다.
1. 우선 그룹별 첫번째 데이터부터 AMT누계를 구합니다.
이때, 당월 + 전월(전월이 없으면 0)이 양수이면 0으로 바꿔야 합니다.
예) B1210001 201401 1000 --> 1000 + 0 = 1000 --> 0
2. 두번째 데이터부터는 당월 AMT + 전월의 합산 결과 AMT를 더하고, 마찬가지로 양수면 0으로 바꿔줍니다.
예) B1210001 201402 -3000 --> -3000 + 0 = -3000
3. 이 프로세스로 개인번호의 마감년월이 끝날때까지 누계를 구합니다.
(B1210001 201401 ~ 201407)
한방 쿼리로 해보려고 생각을 해봐도 답이 나오지를 않네요.
이런식으로 구하는 계산 데이터를 쿼리로 처리할수 있나요?
질문 끝까지 봐주셔서 감사드립니다.
WITH T AS ( SELECT 'B1210001' AS PSN_NO, '201401' AS CLYM, 1000 AS AMT FROM DUAL UNION ALL SELECT 'B1210001' AS PSN_NO, '201402' AS CLYM, -3000 AS AMT FROM DUAL UNION ALL SELECT 'B1210001' AS PSN_NO, '201405' AS CLYM, 5000 AS AMT FROM DUAL UNION ALL SELECT 'B2010001' AS PSN_NO, '201407' AS CLYM, -4000 AS AMT FROM DUAL UNION ALL SELECT 'C2710001' AS PSN_NO, '201402' AS CLYM, -5000 AS AMT FROM DUAL UNION ALL SELECT 'C2710001' AS PSN_NO, '201403' AS CLYM, 1000 AS AMT FROM DUAL UNION ALL SELECT 'C2710001' AS PSN_NO, '201404' AS CLYM, 7000 AS AMT FROM DUAL ) ,T1 AS (SELECT PSN_NO, CLYM , AMT, ROW_NUMBER() OVER (PARTITION BY PSN_NO ORDER BY CLYM) SEQ FROM T ) ,T2 (PSN_NO, CLYM, AMT, CAL_AMT, SEQ) AS ( SELECT PSN_NO, CLYM, AMT, LEAST(AMT,0) CAL_AMT , 1 SEQ FROM ( SELECT PSN_NO, CLYM, AMT, ROW_NUMBER() OVER(PARTITION BY PSN_NO ORDER BY CLYM) RN FROM T ) WHERE RN = 1 UNION ALL SELECT B.PSN_NO, B.CLYM, B.AMT, LEAST(A.CAL_AMT + B.AMT,0), A.SEQ + 1 FROM T2 A, T1 B WHERE A.PSN_NO = B.PSN_NO AND A.SEQ + 1 = B.SEQ ) SELECT PSN_NO, CLYM, AMT, CAL_AMT FROM T2 ORDER BY PSN_NO, CLYM
감사합니다. 도움이 되었습니다. ^^
그런데 궁금한게 아래에서 T1은 위쪽에 있는 상위집합인데 조인이 되는군요.
진짜 공부좀 해야겠네요 ㅠㅠ
저는 뷰가 (T1, T2) 만들어지는 과정이 각각의 뷰가 DEPTH가 깊은 부분부터 만들기 시작해서 두개가 다 생성된 뒤에야 서로를 참조 할 수 있는줄 알았는데 먼저 선언한 뷰가 있으면(T1), 다음 뷰(T2)를 생성할때 하위단에서 먼저 선언한 뷰(T1)를 참조할수 있는건가요?
UNION
ALL
SELECT
B.PSN_NO, B.CLYM, B.AMT, LEAST(A.CAL_AMT + B.AMT,0), A.SEQ + 1
FROM
T2 A, T1 B
WHERE
A.PSN_NO = B.PSN_NO
AND
A.SEQ + 1 = B.SEQ