by 곤 [SQL Query] [2023.06.16 14:41:02]
ROW | Col1 | Col2 | Col3 |
1 | A | 202306 | 5000 |
2 | B | 202306 | 2000 |
3 | C | 202306 | 50 |
해당 테이블에서 A+B를 더한 Col3값을 추가하고
총 4개의 ROW를 이용해 다시 A대비 (A+B), A대비 C의 비율을 각각 추가하여 표현하고 싶습니다.
ROW | Col1 | Col2 | Col3 |
1 | A | 202306 | 5000 |
2 | B | 202306 | 2000 |
3 | C | 202306 | 50 |
4 | A+B | 202306 | 3000 |
5 | (A+B)/A | 202306 | 60% |
6 | C/A | 202606 | 1% |
기존의 데이터에 연산된 ROW를 추가하여 함께 보여줄 방법이 없을까요?
-- 결과 기준이면 'B'가 -2000 이 맞겠네요. WITH tbl AS ( select 1 as vRow, 'A' as vCol1, '202306' as vCOl2, 5000 as vCol3 from Dual union all select 2 as vRow, 'B' as vCol1, '202306' as vCOl2, -2000 as vCol3 from Dual union all select 3 as vRow, 'C' as vCol1, '202306' as vCOl2, 50 as vCol3 from Dual ) SELECT ROW_NUMBER() over(ORDER BY A.vRow, B.vRow) AS colRow , CASE WHEN A.vRow IN (1) THEN B.vCol1 WHEN ROW_NUMBER() over(ORDER BY A.vRow, B.vRow) = 4 THEN 'A+B' WHEN ROW_NUMBER() over(ORDER BY A.vRow, B.vRow) = 5 THEN '(A+B)/A' WHEN ROW_NUMBER() over(ORDER BY A.vRow, B.vRow) = 6 THEN 'C/A' END col1 , B.vCOl2 col2 , CASE WHEN A.vRow IN (1) THEN TO_CHAR(B.vCol3) WHEN ROW_NUMBER() over(ORDER BY A.vRow, B.vRow) = 4 THEN TO_CHAR(B.vCol3 + A.vCol3) WHEN ROW_NUMBER() over(ORDER BY A.vRow, B.vRow) = 5 THEN TO_CHAR((B.vCol3 + lag(B.vCol3) over(ORDER BY A.vRow, B.vRow))/lag(B.vCol3) over(ORDER BY A.vRow, B.vRow)*100)||'%' WHEN ROW_NUMBER() over(ORDER BY A.vRow, B.vRow) = 6 THEN TO_CHAR((A.vCol3 / B.vCol3)*100)||'%' END Col3 FROM tbl A, tbl B WHERE A.vRow IN (1) OR ( A.vCol1 = 'B' AND B.vCol1 IN ('A', 'B') ) OR (A.vCol1 = 'C' AND B.vCol1 = 'A')
각 월마다 A,B,C는 반드시 존재한다는 가정하에...
WITH LST AS ( SELECT 1 RN, 'A' COL1, '202306' COL2, 5000 COL3 FROM DUAL UNION ALL SELECT 2 RN, 'B' COL1, '202306' COL2, 2000 COL3 FROM DUAL UNION ALL SELECT 3 RN, 'C' COL1, '202306' COL2, 50 COL3 FROM DUAL UNION ALL SELECT 1 RN, 'A' COL1, '202307' COL2, 1000 COL3 FROM DUAL UNION ALL SELECT 2 RN, 'B' COL1, '202307' COL2, 2000 COL3 FROM DUAL UNION ALL SELECT 3 RN, 'C' COL1, '202307' COL2, 50 COL3 FROM DUAL ), SUM_AB AS ( SELECT COL2, SUM(COL3) AS SUM_AB FROM LST WHERE COL1 IN ('A', 'B') GROUP BY COL2 ), A_DATA AS ( SELECT COL2, COL3 FROM LST WHERE COL1 = 'A' ), C_DATA AS ( SELECT COL2, COL3 FROM LST WHERE COL1 = 'C' ) SELECT * FROM LST UNION ALL SELECT 4 RN, 'A+B' COL1, LST.COL2, SUM_AB.SUM_AB AS COL3 FROM LST JOIN SUM_AB ON LST.COL2 = SUM_AB.COL2 WHERE LST.COL1 = 'A' UNION ALL SELECT 5 RN, '(A+B)/A' COL1, LST.COL2, CASE WHEN A_DATA.COL3 = 0 THEN NULL ELSE SUM_AB.SUM_AB / A_DATA.COL3 END COL3 FROM LST JOIN SUM_AB ON LST.COL2 = SUM_AB.COL2 JOIN A_DATA ON LST.COL2 = A_DATA.COL2 WHERE LST.COL1 = 'A' UNION ALL SELECT 6 RN, 'C/A' COL1, LST.COL2, CASE WHEN A_DATA.COL3 = 0 THEN NULL ELSE C_DATA.COL3 / A_DATA.COL3 END COL3 FROM LST JOIN A_DATA ON LST.COL2 = A_DATA.COL2 JOIN C_DATA ON LST.COL2 = C_DATA.COL2 WHERE LST.COL1 = 'A' ORDER BY COL2, RN;
WITH t AS ( SELECT 'A' gb, '202306' ym, 5000 v FROM dual UNION ALL SELECT 'B', '202306', 2000 FROM dual UNION ALL SELECT 'C', '202306', 50 FROM dual ) SELECT ROW_NUMBER() OVER(PARTITION BY ym ORDER BY DECODE(gb, 'A-B', 'D', '(A-B)/A', 'E', 'C/A', 'F', gb)) rn , a.* FROM (SELECT ym , a || '' a , b || '' b , c || '' c , a-b || '' "A-B" , ROUND((a - b) / a * 100, 2) || '%' "(A-B)/A" , ROUND( c / a * 100, 2) || '%' "C/A" FROM (SELECT * FROM t PIVOT (MIN(v) FOR gb IN ('A' a, 'B' b, 'C' c)) ) ) UNPIVOT (v FOR gb IN (a, b, c, "A-B", "(A-B)/A", "C/A")) a ;
WITH t AS ( SELECT 'A' gb, '202306' ym, 5000 v FROM dual UNION ALL SELECT 'B', '202306', 2000 FROM dual UNION ALL SELECT 'C', '202306', 50 FROM dual ) SELECT ROW_NUMBER() OVER(PARTITION BY ym ORDER BY DECODE(gb, 'A-B', 'D', '(A-B)/A', 'E', 'C/A', 'F', gb)) rn , a.* FROM (SELECT * FROM t MODEL PARTITION BY (ym) DIMENSION BY (CAST(gb AS VARCHAR2(10)) gb) MEASURES (CAST(v AS VARCHAR2(10)) v) RULES ( v['A-B'] = v['A'] - v['B'] , v['(A-B)/A'] = ROUND((v['A'] - v['B']) / v['A'] * 100, 2) || '%' , v['C/A'] = ROUND( v['c'] / v['A'] * 100, 2) || '%' ) ) a ;