계층쿼리 뽑고싶은 계층만 뽑기 쿼리 질문드립니다. 0 10 3,770

by 강서꽃미남 [SQL Query] CONNECT BY level 계층구조 [2012.03.12 21:05:39]



안녕하세요.

하루종일 고민하다가 글을 쓰게 되네요.

질문입니다.

마스터 테이블에 최상위 1레벨 부터 6레벨 까지 계층쿼리로 짜져 있습니다.

그런데, 제가 SELECT를 2레벨 을 하고 그다음 바로 3,4,5레벨을 제외한 6레벨 이 나오는 쿼리를 짜고 싶은데요.

2레벨 - 6레벨 이런식으로 보여지게요.

SELECT PARENTS_CD AS 부모코드
    , CHANNEL AS 채널코드
    , NAME AS 채널명
, SYS_CONNECT_BY_PATH (LEVELS, '/') LEVEL_PATH 
  FROM HF_MST_CHANNEL
START WITH LEVELS IN (SELECT LEVELS
    FROM HF_MST_CHANNEL
   WHERE LEVELS NOT IN ('1', '3', '4', '5'))
CONNECT BY PRIOR CHANNEL = PARENTS_CD
   AND LEVEL < 2
  ORDER BY LEVEL_PATH


이렇게 짜보니.. 2레벨 과 6레벨 나오긴하는데 밑으로 쭉나오네요...

부모코드   채널코드    채널명 level_path
   T   3레벨것(코드)   채널명     /2
   .
   .
   .
S110   최하위코드 (자신코드) 채널명 /6

이런 식으로 나오게 되는데요.
각각 그 위에 부모코드가 존재하구요

제가 나타내고 싶은 것은

부모코드 채널코드 채널명 LEVEL_PATH
옆으로.. 쭉 나타난다고 해야하나...

2레벨에 하위에 맞는 6레벨데이터가 딱딱 나왔으면 좋겠습니다.
그런데 2레벨 data가 120 개 밖에 안되고 6레벨은 많은 row를 가지고 있어서 오른쪽으로 나타내기도 곤란할것 같고..

이런경우 어떻게 해야하나요.

2, 6레벨 들만 뽑아서 6레벨은 2레벨 어떤 채널코드 밑의 것이다 라고 나타내고 싶습니다.


도움부탁드립니다.

by 마농 [2012.03.13 08:48:52]
SELECT CONNECT_BY_ROOT root_channel
     , SUBSTR(SYS_CONNECT_BY_PATH(channel, '/'), 2) channels
     , SUBSTR(SYS_CONNECT_BY_PATH(name, '/'), 2) names
     , SUBSTR(SYS_CONNECT_BY_PATH('('||channel||')'||name, '/'), 2) channelnames
  FROM hf_mst_channel
 WHERE levels = '6' -- 결과조건
 START WITH levels = '2' -- 시작조건
 CONNECT BY PRIOR channel = parents_cd -- 계층조건
;

by 강서꽃미남 [2012.03.13 09:53:52]

마농님 답변감사합니다.
추가 질문이 있습니다.
지금 이 쿼리대로 날리게 되면, ROW수가 엄청나게 나옵니다. 중복된 결과가 존재하고요
그러나 중복된 결과가 존재하는이유는 달마다 결과가 존재해서 입니다.
1월에 - 값
2월에 - 값
총 이런식으로 12건씩 있기 때문인데요.

SELECT *
  FROM HF_MST_CHANNEL
WHERE LEVELS = '1'
UNION ALL
SELECT *
  FROM HF_MST_CHANNEL
 WHERE LEVELS = '2'
UNION ALL
SELECT *
  FROM HF_MST_CHANNEL
 WHERE LEVELS = '3'
 UNION ALL
SELECT *
  FROM HF_MST_CHANNEL
 WHERE LEVELS = '4'
 UNION ALL
SELECT *
  FROM HF_MST_CHANNEL
 WHERE LEVELS = '5'
UNION ALL
SELECT *
  FROM HF_MST_CHANNEL
 WHERE LEVELS = '6'

을 통해 ROW수를 확인해보면 11640 ROW가 나옵니다.
저렇게 쿼리를 날리면 수많은 로우가 조건에 포함되는 것들이 다 나오는듯 하는데...
CONNECT BY PRIOR 부분을 잘 이해가 안됩니다.
결과값이 11640로우보다 작은
2레벨 120 ROW
6레벨 10296 ROW
만 도출되야 하는것 아닌가 합니다..

이론이 틀린건가요.. 계층쿼리가 너무 어렵네요..
2레벨 120 + 6레벨 10296 값만 나와야 하는것 아닌가 해서 질문드립니다.

by 마농 [2012.03.13 09:59:01]

월마다 다르다는 표현을 하셨는데요.
월에 대한 조건을 계층조건에 추가해야 할듯 하는데요.
AND PRIOR 월 = 월
시작조건이나 결과조건에도 조건을 줘야 할지는 요구사항에 따라 달라질듯 하구요.
명확한 요구사항을 알아야 합니다.

by 강서꽃미남 [2012.03.13 10:28:31]




우선 감사의 말씀드립니다.

상세 정보입니다.



유니온 올로 본 결과는
테이블에 데이터가 이런식으로 존재를 합니다.

이 결과를
C110~ C1XX 까지 LEVEL2 의 120 row
와 바로 6레벨의 10296 row를 표현하고 싶은 것입니다.!


by 마농 [2012.03.13 15:59:56]

그림이 안보이네요.
계층조건은 추가해 보셨나요?

by 손님 [2012.03.13 20:06:13]

by 강서꽃미남 [2012.03.13 20:13:34]

죄송합니다.

답이 늦었습니다.

사진이 안올라가네요.


테이블 현황이 지금

YEAR MONTH CHANNEL PARENTS_CD NAME LEVELS
2012 JAN T   CHANNEL  매장     1 -->최상위레벨입니다. 
.
.
.
2012  JAN   C150 T   직영     2 -->2레벨입니다. 
.
.
.
2012  JAN   BY01   S631    ~~  6     -->6레벨입니다.

이런식으로 데이터가 입력되어 있습니다.

보면 2012년 1월부터 12월까지 있는데, 지금 알려고하는것은 2012년 Jan 데이터만 알면됩니다.
그래서 WHERE절 조건에
   AND YEAR = '2012'
   AND MONTH = 'Jan' 으로 줬습니다.


그래서 마농님께서 짜신 쿼리에 where절 조건 추가했구요,



SELECT 
   CONNECT_BY_ROOT CHANNEL
, SUBSTR (SYS_CONNECT_BY_PATH (CHANNEL, '^'), 2) CHANNELS
, SUBSTR (SYS_CONNECT_BY_PATH (NAME, '^'), 2) NAMES
, SUBSTR (SYS_CONNECT_BY_PATH ('(' || CHANNEL || ')' || NAME, '^'),2) CHANNE_LNAMES
  FROM HF_MST_CHANNEL
WHERE LEVELS = '6'     -- 결과조건
START WITH LEVELS = '2'     -- 시작조건
CONNECT BY PRIOR CHANNEL = PARENTS_CD   -- 계층조건
   AND YEAR = '2012'
   AND MONTH = 'Jan'  

계층조건 추가를 하려다가 어떻게 잡아줘야 할지 모르겠습니다.

내부 루프를 통해서 2레벨부터 6레벨 까지 조인을 해줘야 나오는것인지.
LEVEL2 의 10row,
LEVEL6 의 858row 만 표현되면 됩니다.    ==> 12년 Jan이란 조건으로 검색했을 경우의 로우

그런데 위 쿼리되로 돌리면 858 로우만 표시가 되네요..

조건을 어떻게 줘야할지 조언 부탁드립니다.




by 마농 [2012.03.14 09:39:08]
시작조건, 계층조건, 결과조건
이 세가지가 의미가 다 다르고 잘 구분해서 사용하셔야 합니다.
SELECT CONNECT_BY_ROOT channel root_channel
     , SUBSTR(SYS_CONNECT_BY_PATH(channel, '/'), 2) channels
     , SUBSTR(SYS_CONNECT_BY_PATH(name, '/'), 2) names
     , SUBSTR(SYS_CONNECT_BY_PATH('('||channel||')'||name, '/'), 2) channelnames
  FROM hf_mst_channel
 WHERE levels = '6' -- 결과조건
 START WITH levels = '2'
   AND year = '2012'
   AND month = 'Jan' -- 시작조건
 CONNECT BY PRIOR channel = parents_cd
   AND PRIOR year = year
   AND PRIOR month = month -- 계층조건
;

by 강서꽃미남 [2012.03.14 10:05:21]


SELECT CONNECT_BY_ROOT CHANNEL ROOT_CHANNEL
, SUBSTR(SYS_CONNECT_BY_PATH(CHANNEL, '^'), 2) CHANNELS
, SUBSTR(SYS_CONNECT_BY_PATH(NAME, '^'), 2) NAMES
, SUBSTR(SYS_CONNECT_BY_PATH('('||CHANNEL||')'||NAME, '^'), 2) CHANNELNAMES
  FROM HF_MST_CHANNEL
WHERE LEVELS = '6'      -- 결과조건
  AND CHANNEL IN ( SELECT CHANNEL
    FROM HF_MST_CHANNEL
   WHERE YEAR = '2012'
AND MONTH = 'Jan'
AND LEVELS = 6
AND CHANNEL NOT IN ('CST01')
AND SUBSTR (CHANNEL, 1, 1) 'Z')
  AND PARENTS_CD NOT IN ('C180', 'C130')
START WITH LEVELS = '2'
AND YEAR = '2012'
AND MONTH = 'Jan'     -- 시작조건
CONNECT BY PRIOR CHANNEL = PARENTS_CD
AND PRIOR YEAR = YEAR
AND PRIOR MONTH = MONTH     -- 계층조건

로 조건 추가하여 구현 완료했습니다.! 감사합니다 마농님!!

CONNECT BY PRIOR CHANNEL = PARENTS_CD
AND PRIOR YEAR = YEAR
부분이 이해가 어렵지만, 천천히 해나가니 알것도 같습니다. 조건주기가 애매하네요 ~ 감사합니다^^


by 강서꽃미남 [2012.03.14 10:05:40]
 혹시 저 사용하는 툴은 뭔가요? 많은 분들이 저거 사용하시던데...
댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입