그룹안에 그룹이 속한 경우 조건에 따라 하위 표시 1 10 4,063

by 동동동 [SQL Query] oracle [2022.01.06 18:31:23]


안녕하세요..

오라클 12C를 사용 중입니다.

이게 쿼리로 가능할지 문의 드립니다..

WITH TMP_MST (CD, GB, NM) AS ( 
/* 1.목록 마스터 */
SELECT 'GAA', 'G', '가나다' FROM DUAL UNION ALL   -- G : 하위만 표시
SELECT 'GBA', 'G', '아자자' FROM DUAL UNION ALL
SELECT 'GCA', 'G', '카카카' FROM DUAL UNION ALL
SELECT 'MAA', 'M', '차차차' FROM DUAL UNION ALL   -- M : 자신 포함 하위 표시
SELECT 'SAA', 'S', '123'    FROM DUAL UNION ALL
SELECT 'SAB', 'S', '456'    FROM DUAL UNION ALL
SELECT 'SAC', 'S', '789'    FROM DUAL UNION ALL
SELECT 'SBA', 'S', '321'    FROM DUAL UNION ALL
SELECT 'SBB', 'S', '654'    FROM DUAL UNION ALL
SELECT 'CAA', 'S', '789'    FROM DUAL UNION ALL
SELECT 'CAB', 'S', 'abc'    FROM DUAL UNION ALL
SELECT 'CAC', 'S', 'asd'    FROM DUAL UNION ALL
SELECT 'CAD', 'S', 'kkk'    FROM DUAL
)
/* 2.목록의 그룹정보 */
, TMP_GINFO (G_CD, CD, GB) AS (
SELECT 'GAA',  'CAA', 'S' FROM DUAL UNION ALL
SELECT 'GAA',  'CAB', 'S' FROM DUAL UNION ALL
SELECT 'GAA',  'GBA', 'G' FROM DUAL UNION ALL
SELECT 'GAA',  'SAA', 'S' FROM DUAL UNION ALL
SELECT 'GAA',  'SAB', 'S' FROM DUAL UNION ALL
SELECT 'GAA',  'SAC', 'S' FROM DUAL UNION ALL
SELECT 'GBA',  'SBA', 'S' FROM DUAL UNION ALL
SELECT 'GBA',  'SBB', 'S' FROM DUAL UNION ALL
SELECT 'MAA',  'CAA', 'S' FROM DUAL UNION ALL
SELECT 'MAA',  'CAB', 'S' FROM DUAL UNION ALL
SELECT 'MAA',  'CAC', 'S' FROM DUAL UNION ALL
SELECT 'GCA',  'MAA', 'M' FROM DUAL UNION ALL
SELECT 'GCA',  'SBA', 'S' FROM DUAL UNION ALL
SELECT 'GCA',  'SBB', 'S' FROM DUAL
)

/* 그룹과 하위목록 정보 */
, TMP_GLST AS (
SELECT A.CD AS CD
     , A.CD AS SUB_CD
     , A.NM
     , A.GB
     , 1 AS SORT_KEY
  FROM TMP_MST A
     , (SELECT DISTINCT G_CD FROM TMP_GINFO) B
 WHERE A.CD = B.G_CD
UNION ALL
SELECT B.G_CD AS CD
     , A.CD   AS SUB_CD
     , '    ' || A.NM AS NM
     , A.GB
     , 2 AS SORT_KEY
  FROM TMP_MST A
     , (SELECT DISTINCT G_CD, CD, GB FROM TMP_GINFO) B
 WHERE A.CD = B.CD   
)
/* 그룹과 하위목록 및 그룹에 속하지 않은 목록 정보 */
, TMP_LIST AS (
SELECT * FROM TMP_GLST
UNION ALL
SELECT A.CD AS CD
     , A.CD AS SUB_CD
     , A.NM
     , A.GB
     , 3 AS SORT_KEY
  FROM TMP_MST A
 WHERE NOT EXISTS (SELECT 'X' FROM TMP_GLST B
                    WHERE A.CD = B.SUB_CD
                  )
)
SELECT * FROM TMP_LIST S
ORDER BY DECODE(S.SORT_KEY,1, '1'||S.CD, 2, '1'||S.CD, 3, '2'||S.CD)
       , S.SORT_KEY, S.SUB_CD;

일단 데이터는 1.목록정보테이블과 2.목록의 그룹정보 테이블로 구성되어 있습니다.

해당 테이블의 값들의 구조를 표시하면

CD SUB_CD NM GB SORT_KEY
GAA GAA 가나다 G 1
GAA CAA     789 S 2
GAA CAB     abc S 2
GAA GBA     아자자 G 2
GAA SAA     123 S 2
GAA SAB     456 S 2
GAA SAC     789 S 2
GBA GBA 아자자 G 1
GBA SBA     321 S 2
GBA SBB     654 S 2
GCA GCA 카카카 G 1
GCA MAA     차차차 M 2
GCA SBA     321 S 2
GCA SBB     654 S 2
MAA MAA 차차차 M 1
MAA CAA     789 S 2
MAA CAB     abc S 2
MAA CAC     asd S 2
CAD CAD kkk S 3

 

다음과 같은데요...원하는 결과는 단일 코드를 조회하면 단일코드가 표시되고,

그룹코드를 조회하면 그룹안에 하위와 그룹안에 그룹이 들어 있는 경우도 풀어서 같이 표시하고 싶은 건데요..

'G' 그룹인 경우 자신은 표시 안하고(표시여부 구분값 으로 구분??) 하위만 표시되고

'M'그룹인 경우 자기자신도 표시되고 하위도 표시되게 쿼리로 가능 할까요??

 

예를 들어 GAA를 조회한다고 하면 GAA의 하위와 GAA안에 그룹인 GBA가 들어 있기 때문에 GBA의 하위도 한번에 표시하고 싶습니다.

CD SUB_CD NM 표시여부
GAA GAA 가나다 N
GAA CAA     789 Y
GAA CAB     abc Y
GAA GBA     아자자 N
GAA SAA     123 Y
GAA SAB     456 Y
GAA SAC     789 Y
GAA SBA     321 Y
GAA SBB     654 Y

 

GCA를 조회한다고 하면 GCA의 하위와 GCA안에 그룹인 MAA가 들어 있기 때문에 MAA의 하위도 한번에 표시하고 싶습니다.

CD SUB_CD NM 표시여부
GCA GCA 카카카 N
GCA MAA     차차차 Y
GCA SBA     321 Y
GCA SBB     654 Y
GCA CAA     789 Y
GCA CAB     abc Y
GCA CAC     asd Y

 

순환 구조 같은데 이게 쿼리로만 가능 할련지요?? 많은 조언 부탁드립니다..

by 마농 [2022.01.07 09:18:59]
SELECT b.g_cd
     , a.cd
     , a.nm
  FROM tmp_mst a
  LEFT OUTER JOIN tmp_ginfo b
    ON a.cd = b.cd
 WHERE a.gb != 'G'
 START WITH a.cd = 'GAA'
 CONNECT BY PRIOR a.cd = b.g_cd
;

 


by 동동동 [2022.01.07 09:42:08]

마농님 빠른 답변 정말 감사드립니다...

그룹인 경우 어떤 그룹에서 풀린건지 알기 위해 다음 과 같이 변경해 보았습니다..

SELECT CONNECT_BY_ROOT a.cd AS r_cd
     , b.g_cd
     , a.cd
     , a.nm
     , a.gb
     , decode(a.gb, 'G', 'N', 'Y') VIEW_YN
  FROM tmp_mst a
  LEFT OUTER JOIN tmp_ginfo b
    ON a.cd = b.cd
-- WHERE a.gb != 'G'
 START WITH a.cd = 'GAA'
 CONNECT BY PRIOR a.cd = b.g_cd
;
R_CD G_CD CD NM GB VIEW_YN
GAA   GAA 가나다 G N
GAA GAA CAA 789 S Y
GAA GAA CAB abc S Y
GAA GAA GBA 아자자 G N
GAA GBA SBA 321 S Y
GAA GBA SBB 654 S Y
GAA GAA SAA 123 S Y
GAA GAA SAB 456 S Y
GAA GAA SAC 789 S Y

 

저렇게 하는게 맞을까요??

 

추가로 혹시 전체 마스터 목록에 대해 해당 방식으로 표시를 하려면 어떻게 해야 할련지요??

 

도움 주셔서 감사드립니다...

 

 


by 마농 [2022.01.07 09:59:31]

특정 조건으로 시작하기 위해 START WITH 조건을 준것이므로
모든 행에 대해 다 나오게 하고 싶다면?
START WITH  조건을 빼면 됩니다.
이게 원하는 결과가 맞는지 확인해 보시고.
혹시 아니라면? 이런걸 원하는 걸 수도 있습니다.
최상위 노드로부터 시작
START WITH b.g_cd IS NULL


by 동동동 [2022.01.07 12:42:15]

마농님 답변과 조언 정말 감사드립니다..

전체 목록 조회시 에는 그룹(G, M)은 하위(S) 및 그룹에 그룹이 있는 경우 풀어서 같이 표시하고,

단일(S) 인 경우 그룹에서 표시가 되었으면 추가로 표시를 안하고 그룹에 포함 안된 단일은 표시하고..

좀 복잡하네요...ㅠㅠ

G_CD CD SUB_CD NM GB SORT_KEY  
GAA GAA GAA 가나다 G 1  
GAA GAA CAA     789 S 2  
GAA GAA CAB     abc S 2  
GAA GAA GBA     아자자 G 2  
GAA GAA SAA     123 S 2  
GAA GAA SAB     456 S 2  
GAA GAA SAC     789 S 2  
GAA GBA SBA     321 S 2 --GBA그룹이 GAA에 풀어진것
GAA GBA SBB     654 S 2 --GBA그룹이 GAA에 풀어진것
GBA GBA GBA 아자자 G 1  
GBA GBA SBA     321 S 2  
GBA GBA SBB     654 S 2  
GCA GCA GCA 카카카 G 1  
GCA GCA MAA     차차차 M 2  
GCA GCA SBA     321 S 2  
GCA GCA SBB     654 S 2  
GCA MAA CAA     789 S 2 --MAA그룹이 GCA에 풀어진것
GCA MAA CAB     abc S 2 --MAA그룹이 GCA에 풀어진것
GCA MAA CAC     asd S 2 --MAA그룹이 GCA에 풀어진것
MAA MAA MAA 차차차 M 1  
MAA MAA CAA     789 S 2  
MAA MAA CAB     abc S 2  
MAA MAA CAC     asd S 2  
CAD CAD CAD kkk S 3 -- 아무 그룹에도 속하지 않은 단일 코드

알려주신 방법으로 좀더 확인 해 보겠습니다...

 

감사합니다..꾸벅...


by 마농 [2022.01.07 13:15:46]

START WITH b.g_cd IS NULL 하시면 맞을 것 같은데요?


by 동동동 [2022.01.07 14:31:04]

예..마농님 답변 감사드립니다..

START WITH b.g_cd IS NULL 로 하면 풀린것이 표시되는데..

그룹인 GBA, MAA가 추가로 표시가 안되서요..

G_CD CD SUB_CD NM GB SORT_KEY  
GAA GAA GAA 가나다 G 1  
GAA GAA CAA     789 S 2  
GAA GAA CAB     abc S 2  
GAA GAA GBA     아자자 G 2  
GAA GAA SAA     123 S 2  
GAA GAA SAB     456 S 2  
GAA GAA SAC     789 S 2  
GAA GBA SBA     321 S 2 --GBA그룹이 GAA에 풀어진것
GAA GBA SBB     654 S 2 --GBA그룹이 GAA에 풀어진것
GBA GBA GBA 아자자 G 1 --원래 GBA의 그룹목록
GBA GBA SBA     321 S 2  
GBA GBA SBB     654 S 2  
GCA GCA GCA 카카카 G 1  
GCA GCA MAA     차차차 M 2  
GCA GCA SBA     321 S 2  
GCA GCA SBB     654 S 2  
GCA MAA CAA     789 S 2 --MAA그룹이 GCA에 풀어진것
GCA MAA CAB     abc S 2 --MAA그룹이 GCA에 풀어진것
GCA MAA CAC     asd S 2 --MAA그룹이 GCA에 풀어진것
MAA MAA MAA 차차차 M 1 --원래 MAA그룹 목록
MAA MAA CAA     789 S 2  
MAA MAA CAB     abc S 2  
MAA MAA CAC     asd S 2  
CAD CAD CAD kkk S 3 -- 아무 그룹에도 속하지 않은 단일 코드

by 마농 [2022.01.07 14:55:19]

START WITH a.gb IN ('G', 'M')


by 동동동 [2022.01.07 15:15:43]

와우...마농님 빠른 답변 감사드립니다...

전 한번 깜싸도 보고 난리를 치고 있었네요..ㅠㅠ

그런데..마지막 아무 그룹에도 속하지 않는 단일코드는 누락이 되네요..ㅠㅠ

SELECT CONNECT_BY_ROOT a.cd AS r_cd
     , b.g_cd
     , NVL(b.g_cd, a.cd) AS t_cd
     , a.cd
     , a.nm
     , a.gb
     , decode(a.gb, 'G', 'N', 'Y') VIEW_YN
     , decode(a.gb, 'S', 2, 1) AS SORT_KEY
  FROM tmp_mst a
  LEFT OUTER JOIN tmp_ginfo b
    ON a.cd = b.cd
-- WHERE a.gb != 'G'
--START WITH a.cd = 'GAA'
--START WITH b.g_cd IS NULL
START WITH a.gb IN ('G', 'M')
CONNECT BY PRIOR a.cd = b.g_cd
ORDER BY CONNECT_BY_ROOT a.cd, b.g_cd NULLS FIRST, a.cd

 

지속적인 관심과 답변 감사드립니다...ㅠㅠ


by 마농 [2022.01.07 16:21:26]

START WITH a.gb IN ('G', 'M') OR b.g_cd IS NULL


by 동동동 [2022.01.07 18:38:24]

아..마농님 늦게 까지 정말 감사드립니다..ㅠㅠ

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입