계층쿼리 도움 요청 드립니다 0 8 890

by 오라오라 [SQL Query] [2020.06.03 15:48:07]


안녕하세요~ 계층쿼리 문의 드립니다.
계층쿼리 구문을 지원하지 않는 경우, 아래 "데이터" 를 가지고 아래 "결과" 처럼 추출하려면 어떻게 해야 하나요 ?

어제부터 해보고 있지만 원하는 결과가 안나와서요 ㅠㅠ 도와주세요~~ ㅠㅠ


** 데이터

PARENT_ENT_NM		CHILD_ENT_NM
-------------		        ------------
메뉴					메뉴권한
메뉴권한				권한그룹메뉴권한
메뉴권한				사용자메뉴권한
게시판				게시물
게시물				게시물로그
게시물				게시물댓글
게시물				게시물				
영화 				영화관
영화관				회원
회원					영화

 

** 결과

순환 Level        순환관계 리스트
4                영화 -> 영화관 -> 회원 -> 영화

by 마농 [2020.06.03 17:32:52]

계층 구조 쿼리를 지원하지 않는 DBMS 인가요?
다른 대안을 찾아야 할 것 같습니다.
- 쿼리가 아닌 프로그램으로 구현하던가?
- 재귀함수를 만들어 호출하는 방안
- 최대 가능 레벨을 예측하고, 그만큼 셀프조인하는 방안
결과가 1건만 나왔는데?
- (게시물 -> 게시물) 도 순환인 듯 하구요.
순서만 다른 다음 정보도 순환인 듯 하네요.
- (영화관 -> 회원 -> 영화 -> 영화관)
- (회원 -> 영화 -> 영화관 -> 회원)


by 오라오라 [2020.06.03 17:52:56]

네 계층 구조 쿼리를 지원하지 않습니다. Excel(Access) 에서 SQL 로 구현을 하려다 보니 어렵네요...

혹시 이게 오라클 DB 라면 가능할까요 ? 아래 조건을 만족하면서요...

 

- 최대 가능 레벨은 정확한 예측이 어렵습니다.

- 게시물 -> 게시물 같은 자기 자신을 순환하는 형태는 빠져야 합니다.

- 순서만 다른 정보도 1개만 나오게 하고 싶습니다.


by 마농 [2020.06.03 18:29:53]

예측이 어렵다? 자리수 정도는 예상이 가능하지 않나요?
 - 1자리수 라면 조인으로 풀어볼만 할 듯 하고
 - 2자리수 이상이라면 좀 어려울 듯.
계층 쿼리 지원하는 DB 라면 계층 쿼리로 가능합니다.
 - 순서만 다른 정보도 1개만 나오게 하려면 추가 로직을 구상해야 합니다.
 - 컬럼은 저렇게 2개 뿐인가요? 추가 정보는 없는지?
 - 자식 노드는 유니크해야 할 듯 한데? 게시물 이 중복되네요? 이거 맞는지?


by 오라오라 [2020.06.04 09:19:08]

먼저 답변 감사드립니다. (--)(__)

- 자리수는 1자리수로 예상할 수 있을거 같습니다.
- 컬럼은 저렇게 2개 입니다. 추가 정보는 없습니다.
- 이 데이터는 관계를 맺은 엔터티 정보를 가져온것 입니다.
--- 게시물 -> 게시판(자기참조 관계(글, 댓글)) 로 되어 있어 자식 노드가 유니크 하지 않습니다.
--- 이렇게 자기참조 엔터티도 다른 엔터티와 관계를 맺어 순환될 수 있습니다.

이런 조건의 경우에도 계층 쿼리 지원 없이 조인으로 풀 수 있을까요 ?

아래는 제가 작성해본 SQL 과 결과인데 형편 없네요 ;;

 

SELECT P.PARENT_ENT_NM
     , P.CHILD_ENT_NM
     , C1.PARENT_ENT_NM
     , C1.CHILD_ENT_NM
     , C2.PARENT_ENT_NM
     , C2.CHILD_ENT_NM
     , C3.PARENT_ENT_NM
     , C3.CHILD_ENT_NM
FROM   SUNG.TB_REL P LEFT JOIN SUNG.TB_REL C1 ON (P.CHILD_ENT_NM = C1.PARENT_ENT_NM)
					 LEFT JOIN SUNG.TB_REL C2 ON (C1.CHILD_ENT_NM = C2.PARENT_ENT_NM)
					 LEFT JOIN SUNG.TB_REL C3 ON (C2.CHILD_ENT_NM = C3.PARENT_ENT_NM)
WHERE  1=1
AND    P.PARENT_ENT_NM  <> P.CHILD_ENT_NM
AND    C1.PARENT_ENT_NM <> C1.CHILD_ENT_NM
AND    P.CHILD_ENT_NM  IS NOT NULL
AND    C1.CHILD_ENT_NM IS NOT NULL
AND    C2.CHILD_ENT_NM IS NOT NULL
AND    C3.CHILD_ENT_NM IS NOT NULL 
AND    CONCAT(C1.PARENT_ENT_NM, C1.CHILD_ENT_NM) <> CONCAT(C2.PARENT_ENT_NM, C2.CHILD_ENT_NM) ;

PARENT_ENT_NM|CHILD_ENT_NM|PARENT_ENT_NM|CHILD_ENT_NM|PARENT_ENT_NM|CHILD_ENT_NM|PARENT_ENT_NM|CHILD_ENT_NM|
-------------|------------|-------------|------------|-------------|------------|-------------|------------|
영화           |영화관         |영화관          |회원          |회원           |영화          |영화           |영화관         |
영화관          |회원          |회원           |영화          |영화           |영화관         |영화관          |회원          |
회원           |영화          |영화           |영화관         |영화관          |회원          |회원           |영화          |

 


by 마농 [2020.06.04 09:27:20]

DBMS 가 뭔가요?


by 오라오라 [2020.06.04 10:04:29]

Excel VBA 에서 라이브러리만 추가하여 Excel 을 DB 처럼 사용하는 것인데, Access DB 와 유사한것으로 알고 있습니다.


by 마농 [2020.06.04 13:58:18]

오라클에서 테스트

WITH tb_rel AS
(
SELECT '메뉴' parent_ent_nm, '메뉴권한' child_ent_nm FROM dual
UNION ALL SELECT '메뉴권한', '권한그룹메뉴권한' FROM dual
UNION ALL SELECT '메뉴권한', '사용자메뉴권한'   FROM dual
UNION ALL SELECT '게시판'  , '게시물'           FROM dual
UNION ALL SELECT '게시물'  , '게시물로그'       FROM dual
UNION ALL SELECT '게시물'  , '게시물댓글'       FROM dual
UNION ALL SELECT '게시물'  , '게시물'           FROM dual
UNION ALL SELECT '영화'    , '영화관'           FROM dual
UNION ALL SELECT '영화관'  , '회원'             FROM dual
UNION ALL SELECT '회원'    , '영화'             FROM dual
)
SELECT *
  FROM (SELECT c0.parent_ent_nm nm0
             , c0.child_ent_nm  nm1
             , c1.child_ent_nm  nm2
             , c2.child_ent_nm  nm3
             , c3.child_ent_nm  nm4
             , c4.child_ent_nm  nm5
             , CASE c0.parent_ent_nm
               WHEN c0.child_ent_nm THEN 2
               WHEN c1.child_ent_nm THEN 3
               WHEN c2.child_ent_nm THEN 4
               WHEN c3.child_ent_nm THEN 5
               WHEN c4.child_ent_nm THEN 6
                END is_cycle_lv
          FROM tb_rel c0
          LEFT OUTER JOIN tb_rel c1 ON c0.child_ent_nm = c1.parent_ent_nm AND c1.child_ent_nm != c1.parent_ent_nm AND c0.parent_ent_nm != c0.child_ent_nm
          LEFT OUTER JOIN tb_rel c2 ON c1.child_ent_nm = c2.parent_ent_nm AND c2.child_ent_nm != c2.parent_ent_nm AND c0.parent_ent_nm != c1.child_ent_nm
          LEFT OUTER JOIN tb_rel c3 ON c2.child_ent_nm = c3.parent_ent_nm AND c3.child_ent_nm != c3.parent_ent_nm AND c0.parent_ent_nm != c2.child_ent_nm
          LEFT OUTER JOIN tb_rel c4 ON c3.child_ent_nm = c4.parent_ent_nm AND c4.child_ent_nm != c4.parent_ent_nm AND c0.parent_ent_nm != c3.child_ent_nm
        ) a
-- WHERE is_cycle_lv > 2
;

 


by 오라오라 [2020.06.04 16:47:03]

감사합니다 :)

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