오라클 계층형 쿼리 질문드립니다.! 1 12 2,738

by 보냐스키 [SQL Query] tree 계층 [2015.10.26 10:17:55]


안녕하세요.

오라클 쿼리짜는데 헤매서 질문드립니다..

 

DB 컬럼이 A(1레벨), B(2레벨), C(3레벨), D(4레벨) 가 있다고 칠 때

A

    B

       C

          D

          D

       C

          D

    B

       C

         D

A

 

이런 식으로 출력하고 싶습니다 .

 

쿼리 초보에게 도움 부탁드려요.

by 우리집아찌 [2015.10.26 10:20:15]

http://www.gurubee.net/lecture/1300


by 보냐스키 [2015.10.26 10:40:29]

잘 찾아보지도 않고 질문을 올렸네요..

답변 감사합니다!


by 창조의날개 [2015.10.26 10:45:28]

변수가 너무 많네요..

 

샘플 데이터와 출력을 원하는 데이터 형태를 함께 올려 주셔야 할 듯 합니다.

 

초기 데이터의 형태와 출력 형태에 따라서 쿼리의 차이가 많이 날 듯 합니다..


by 보냐스키 [2015.10.26 12:44:07]

TABLE 1

PJT_SQ, DEPT, UNIT, CONTENT

1001       부서1    유닛1  내용1

1001       부서2    유닛2  내용2

1002       부서1    유닛3  내용3

1002       부서2    유닛4  내용3

 

TABLE2

PJT_SQ, PJT_NM

1001        프로젝트1

1002        프로젝트2

 

식으로 2개 테이블을 조인하려고 합니다.

 

출력형태는

1번컬럼       2번컬럼

프로젝트1

   DEPT1

       UNIT1

                    CONTENT

                    CONTENT

       UNIT2

                    CONTENT

   DEPT2

       UNIT1

                    CONTENT

  

프로젝트2

   DEPT1

       UNIT1

                   CONTENT

 

 

화면단에서는 프로젝트를 열면 프로젝트에 속한 DEPT가 나오고

거기서 DEPT를 또 열면 UNIT이 나오고 유닛을 열면 나머지 유닛에 속한 내용이 나오는 식입니다.

 

 부모 자식관계가 마땅히 없는데 어떤식으로 해야할지요..

예제 봐봣는데도 햇갈리네요

                       

 

 


by 창조의날개 [2015.10.26 15:00:28]


어차피 순차적으로 선택하는 거라면 아래처럼 쿼리르 만들어서 사용하시는 편이 좋을 듯 합니다.

1. 프로젝트 열기
   SELECT PJT_SQ, PJT_NM
   FROM TABLE2
   ;

2. 선택한 프로젝트의 DETP 보이기
   SELECT DEPT
   FROM TABLE1
   WHERE PJT_SQ = '1001'
   ;

3. 선택한 DETP의 UNIT 보이기
   SELECT UNIT
   FROM TABLE1
   WHERE PJT_SQ = '1001'
     AND DETP = '부서1'
   ;

4. 선택한 UNIT의 CONTENT 보이기
   SELECT CONTENT
   FROM TABLE1
   WHERE PJT_SQ = '1001'
     AND DETP = '부서1'
     AND UNIT = '유닛1'
   ;

이미 테이블 구조를 제귀호출 형태로 만들지 않았기 때문에..
기존 데이터들을 조합해서 트리 구조로 만들면..
앞으로 프로젝트가 많아지면 많은 데이터들을 다시 모두 조합하기 위해
쓸때없이 전체 데이터를 읽어야 하는 일이 발생해서 효율적으로 좋지 않을 수 있습니다.

만약 위에 출력 형태처럼 전체 데이터를 보여줘야 하는 화면이 있나요?


by 보냐스키 [2015.10.26 15:28:18]

답변 감사합니다!

출력형태처럼 뽑아야 될 화면이 있습니다...

저도 따로 뽑아서 WITH절로 만들어서 계층형으로 뽑으려고 했습니다..

그런데 START WITH를 부모(프로젝트) - 자식(DEPT) 은 할 수 있을 것 같은데

UNIT의 자식 DEPT는 어떻게 처리해야 될지 감이 안잡히네요..


by 창조의날개 [2015.10.26 17:45:07]

WITH TABLE1(PJT_SQ, DEPT, UNIT, CONTENT) AS(
SELECT '1001',       '부서1',    '유닛1',  '내용1' FROM DUAL UNION ALL
SELECT '1001',       '부서2',    '유닛2',  '내용2' FROM DUAL UNION ALL
SELECT '1002',       '부서1',    '유닛3',  '내용3' FROM DUAL UNION ALL
SELECT '1002',       '부서2',    '유닛4',  '내용3' FROM DUAL
)
, TABLE2(PJT_SQ, PJT_NM) AS (
SELECT '1001',        '프로젝트1' FROM DUAL UNION ALL
SELECT '1002',        '프로젝트2' FROM DUAL
)
SELECT LPAD(' ', 4*(LEVEL-1)) || CD_NM AS CD_NM
     , DECODE(CONNECT_BY_ISLEAF,0,LPAD(' ', 4*(LEVEL-1)) || CD_NM) COL1
     , DECODE(CONNECT_BY_ISLEAF,1,CD_NM) COL2
FROM (
      SELECT PJT_SQ CD
           , NULL UP_CD
           , PJT_NM CD_NM
      FROM TABLE2
      UNION ALL
      SELECT DECODE(LV, 1, PJT_SQ||DEPT, 2,  PJT_SQ||DEPT||UNIT, 3, CONTENT) CD
           , DECODE(LV, 1, PJT_SQ, 2, PJT_SQ||DEPT, 3,  PJT_SQ||DEPT||UNIT) UP_CD
           , DECODE(LV, 1, DEPT, 2,  UNIT, 3, CONTENT) CD_NM
      FROM TABLE1 AA
         , (SELECT LEVEL LV FROM DUAL CONNECT BY LEVEL <= 3) BB
)
START WITH UP_CD IS NULL
CONNECT BY PRIOR CD = UP_CD
;

 


by 보냐스키 [2015.10.27 08:38:17]

감사합니다!!

많은 도움 되었습니다^^

 

혹시 upCode를 자신의 바로 위 상위만 나오게할 순 없을까요.??


by 창조의날개 [2015.10.27 14:55:17]

upCode를 자신의 바로 위 상위만 나오게 한다는 뜻이?

 

쿼리에서 임의로 만들어 놓은 up_cd는 최상위 부터 문자열을 합쳤는데..

모두 합치지 말고 상위 것만 있었으면 한다는 뜻인가요?

만약 그렇게 하려면 현재 샘플 쿼리 처럼 코드명으로 한다면 안되구요..

(같은 코드명이 있을 경우 중복이 발생하기 때문에...)

유니크한 코드로 만들어진 것이라면 구지 지금처럼 문자열로 합쳐서 쓸 필요는 없겠네요..

그냥 상위 코드로만 정의 해도 되겠죠..

 

실제 데이터가 아니라 참고용으로 사용하시면 됩니다..

 

 


by 보냐스키 [2015.10.27 15:14:49]
 CODE 컬럼  UP_CODE 컬럼
 PJT01  
 DEPT01  PJT01
 DEPT02  PJT01
 UNIT01  DEPT02
 UNIT02  DEPT02

 

이런식으로 뽑고 싶은데 수정이 많이 들어가야될까요?,,

아 계층형쿼리 어렵네요 .ㅠ


by 창조의날개 [2015.10.27 17:30:26]

SELECT NULL UP_CD
     , PJT_SQ CD
FROM TABLE2
UNION ALL
SELECT DECODE(LV, 1, PJT_SQ, 2, DEPT, 3,  UNIT) UP_CD
     , DECODE(LV, 1, DEPT, 2,  UNIT, 3, CONTENT) CD
FROM TABLE1 AA
 , (SELECT LEVEL LV FROM DUAL CONNECT BY LEVEL <= 3) BB
;

이렇게 하면 됩니다만..

전제 조건으로 PJT_SQ, DEPT, UNIT들이 서로 중복 되지 않아야 합니다.

그래야만 아래처럼 쿼리 했을때 트리구조가 완성이 됩니다.


SELECT DECODE(CONNECT_BY_ISLEAF,0,LPAD(' ', 4*(LEVEL-1)) || CD) COL1
     , DECODE(CONNECT_BY_ISLEAF,1,CD) COL2
FROM (
    SELECT NULL UP_CD
         , PJT_SQ CD
    FROM TABLE2
    UNION ALL
    SELECT DECODE(LV, 1, PJT_SQ, 2, DEPT, 3,  UNIT) UP_CD
         , DECODE(LV, 1, DEPT, 2,  UNIT, 3, CONTENT) CD
    FROM TABLE1 AA
     , (SELECT LEVEL LV FROM DUAL CONNECT BY LEVEL <= 3) BB
)
START WITH UP_CD IS NULL
CONNECT BY PRIOR CD = UP_CD
;

 


by 마농 [2015.10.28 08:51:51]

위 질문의 구조대로라면
상위 코드에 해당하는 dept 나 unit 값은 당연히 중복이 있겠지요.
UNAON ALL 대신 UNION 을 사용한다면 중복제거가 되겠네요.

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