1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | WITH T AS ( SELECT 101 ID, 1 IDX , 1 LVL, 'AAAAA' P_CODE, 'BBBBB' C_CODE, '강호동' NAME FROM DUAL UNION ALL SELECT 102, 2, 2, 'BBBBB' , 'CCCCC' , '차인표' FROM DUAL UNION ALL SELECT 103, 3, 3, 'CCCCC' , 'JJJJJ' , '강부자' FROM DUAL UNION ALL SELECT 104, 4, 3, 'CCCCC' , 'DDDDD' , '유재석' FROM DUAL UNION ALL SELECT 105, 5, 4, 'DDDDD' , 'KKKKK' , '이효리' FROM DUAL UNION ALL SELECT 106, 6, 4, 'DDDDD' , 'LLLLL' , '김민희' FROM DUAL UNION ALL SELECT 107, 7, 3, 'CCCCC' , 'EEEEE' , '김혜자' FROM DUAL UNION ALL SELECT 108, 8, 4, 'EEEEE' , 'FFFFF' , '고두심' FROM DUAL UNION ALL SELECT 109, 9, 5, 'FFFFF' , 'MMMMM' , '이영자' FROM DUAL UNION ALL SELECT 110, 10, 4, 'EEEEE' , 'NNNNN' , '전현무' FROM DUAL UNION ALL SELECT 111, 11, 4, 'EEEEE' , 'OOOOO' , '나혜심' FROM DUAL UNION ALL SELECT 112, 12, 4, 'EEEEE' , 'PPPPP' , '고수' FROM DUAL UNION ALL SELECT 113, 13, 4, 'EEEEE' , 'GGGGG' , '차두리' FROM DUAL UNION ALL SELECT 114, 14, 5, 'GGGGG' , 'MMMMM' , '이영자' FROM DUAL UNION ALL SELECT 115, 15, 4, 'EEEEE' , 'HHHHH' , '이영표' FROM DUAL UNION ALL SELECT 116, 16, 5, 'HHHHH' , 'MMMMM' , '이영자' FROM DUAL UNION ALL SELECT 117, 17, 3, 'CCCCC' , 'QQQQQ' , '손흥민' FROM DUAL UNION ALL SELECT 118, 18, 3, 'CCCCC' , 'IIIII' , '김민재' FROM DUAL UNION ALL SELECT 119, 19, 4, 'IIIII' , 'MMMMM' , '이영자' FROM DUAL UNION ALL SELECT 120, 20, 4, 'IIIII' , 'RRRRR' , '이경규' FROM DUAL UNION ALL SELECT 121, 21, 1, 'AAAAA' , 'UUUUU' , '박지성' FROM DUAL UNION ALL SELECT 122, 22, 2, 'UUUUU' , 'ZZZZZ' , '곽부성' FROM DUAL UNION ALL SELECT 123, 23, 3, 'ZZZZZ' , 'SSSSS' , '원빈' FROM DUAL UNION ALL SELECT 124, 24, 3, 'ZZZZZ' , 'TTTTT' , '이나영' FROM DUAL ) SELECT T1.ID, T1.IDX, T1.LVL, T1.P_CODE, T1.C_CODE, T1. NAME , T2. NAME P_NAME FROM T T1 , ( SELECT C_CODE , NAME FROM T GROUP BY C_CODE , NAME ) T2 WHERE T1.P_CODE = T2.C_CODE(+) ORDER BY IDX; |
위와 같이 계층형 구조의 데이터가 있다고 가정합니다.
ID는 데이터이 PK값이고 IDX는 전체 데이터의 순번입니다.
전체 데이터의 구조가 LVL이 1이고 P_CODE가 'AAAAA'인 데이터가 전체데이터를 보면 두군데가 존재합니다.
실제로는 더 많이 존재합니다.
요점은 하나의 Row에 2개의 컬럼(P_NAME, 부모코드의 ID(PK)값)을 추가해서 표현하고 싶습니다.
이때 제약조건이 있는데 부모를 찾아가는 과정에서 자신의 가장 최상위 부모인 'AAAAA'코드를 만나면 그 범위를 벗어나면 안 됩니다.
즉, 위 sample 데이터 기준으로 보면 IDX 1 ~20까지가 하나의 데이터셋이고 21~24까지가 또 하나의 데이터셋이라고 보고 부모의 이름을 그 범위안에서 찾아야 한다 입니다.
제가 글로 설명이 잘 되었는지 모르겠습니다. ㅠㅠ
고수님들의 도움 부탁드립니다.
참고로 실제 데이터의 크기는 대략 2000건정도입니다.
감사합니다.
1. 그룹을 나누는 이유는 C_CODE가 'RRRRR'라는 데이터를 보면
SELECT 120, 20, 4, 'IIIII', 'RRRRR', '이경규' FROM DUAL --> 부모의 PK는 118
부모를 찾아과는 과정에서 'IIII'를 C_CODE로 가지는 데이터가 해당 그룹을 벗어나서 다른 그룹에도 존재할수 있기 때문입니다.
2. C_CODE는 중복되는 것이 맞습니다. 실제 데이터가 그렇게 구성되어 있어요.
제가 계층구조라는 표현을 써서 오해의 소지가 있었던거 같아요. 데이터 구조는 마치 계층형 구조처럼 Level 부모코드, 자식코드로 이루어져 있지만 자식코드(C_CODE)만 놓고 보면 중복데이터가 있습니다.
하지만 (부모 + 자식)을 하나로 놓고 보면 중복데이터가 없어요.
샘플 데이터를 놓고 보면 최상위 노드가
SELECT 101 ID, 1 IDX , 1 LVL, 'AAAAA' P_CODE, 'BBBBB' C_CODE, '강호동' NAME FROM DUAL
SELECT 121, 21, 1, 'AAAAA', 'UUUUU', '박지성' FROM DUAL
이렇게 2개가 존재하고 이 노드를 기준으로 계층형(?) 구조를 가지고 있어요. 또 계층형 구조라는 표현을 썼는데 달리 표현할 말이 떠오르지 않아서요.
전체 데이터를 놓고 보면 하나의 그룹(?)을 복사 붙여놓고 최상위 부모 아래로 다시 데이터를 구성했다고 보면 되는 것 같아요. 제가 쓰면서도 무슨말인지.... ;;
아무튼 감사합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | WITH t AS ( SELECT 101 id, 1 idx, 1 lvl, 'AAAAA' p_code, 'BBBBB' c_code, '강호동' name FROM dual UNION ALL SELECT 102, 2, 2, 'BBBBB' , 'CCCCC' , '차인표' FROM dual UNION ALL SELECT 103, 3, 3, 'CCCCC' , 'JJJJJ' , '강부자' FROM dual UNION ALL SELECT 104, 4, 3, 'CCCCC' , 'DDDDD' , '유재석' FROM dual UNION ALL SELECT 105, 5, 4, 'DDDDD' , 'KKKKK' , '이효리' FROM dual UNION ALL SELECT 106, 6, 4, 'DDDDD' , 'LLLLL' , '김민희' FROM dual UNION ALL SELECT 107, 7, 3, 'CCCCC' , 'EEEEE' , '김혜자' FROM dual UNION ALL SELECT 108, 8, 4, 'EEEEE' , 'FFFFF' , '고두심' FROM dual UNION ALL SELECT 109, 9, 5, 'FFFFF' , 'MMMMM' , '이영자' FROM dual UNION ALL SELECT 110, 10, 4, 'EEEEE' , 'NNNNN' , '전현무' FROM dual UNION ALL SELECT 111, 11, 4, 'EEEEE' , 'OOOOO' , '나혜심' FROM dual UNION ALL SELECT 112, 12, 4, 'EEEEE' , 'PPPPP' , '고수' FROM dual UNION ALL SELECT 113, 13, 4, 'EEEEE' , 'GGGGG' , '차두리' FROM dual UNION ALL SELECT 114, 14, 5, 'GGGGG' , 'MMMMM' , '이영자' FROM dual UNION ALL SELECT 115, 15, 4, 'EEEEE' , 'HHHHH' , '이영표' FROM dual UNION ALL SELECT 116, 16, 5, 'HHHHH' , 'MMMMM' , '이영자' FROM dual UNION ALL SELECT 117, 17, 3, 'CCCCC' , 'QQQQQ' , '손흥민' FROM dual UNION ALL SELECT 118, 18, 3, 'CCCCC' , 'IIIII' , '김민재' FROM dual UNION ALL SELECT 119, 19, 4, 'IIIII' , 'MMMMM' , '이영자' FROM dual UNION ALL SELECT 120, 20, 4, 'IIIII' , 'RRRRR' , '이경규' FROM dual UNION ALL SELECT 121, 21, 1, 'AAAAA' , 'UUUUU' , '박지성' FROM dual UNION ALL SELECT 122, 22, 2, 'UUUUU' , 'ZZZZZ' , '곽부성' FROM dual UNION ALL SELECT 123, 23, 3, 'ZZZZZ' , 'SSSSS' , '원빈' FROM dual UNION ALL SELECT 124, 24, 3, 'ZZZZZ' , 'TTTTT' , '이나영' FROM dual ) SELECT a.id, a.idx, a.lvl, a.p_code, a.c_code, a. name , MAX (b.idx) p_idx , MAX (b.id) KEEP(DENSE_RANK FIRST ORDER BY b.idx DESC ) p_id , MAX (b. name ) KEEP(DENSE_RANK FIRST ORDER BY b.idx DESC ) p_name FROM t a LEFT OUTER JOIN t b ON a.idx > b.idx AND a.p_code = b.c_code GROUP BY a.id, a.idx, a.lvl, a.p_code, a.c_code, a. name ; |
1. 부모코드를 셀프조인 하는데
2. idx 가 작은 부분만 조인
3. 그중에서 idx 가 가장 큰것만 추출