경로 만들기 || 역계층구조 관련 쿼리 질문드립니다. - 질문수정 0 7 4,587

by 커피요쿠르트d [SQLServer] SQLServer 경로 CONNECT_BY SYS_CONNECT_BY_PATH 계층 [2014.07.15 19:36:04]


수고하십니다. 

- db -  sql server 2005

쿼리 짜다가 잘 안풀려서 문의 드립니다. ㅜㅜ

경로 만들기 || 역계층구조 인데요. 

아래와 같은 자료가 있을경우..

with test_TBL (CHILD , PARENT , step) 
as
(
select 'Z' as CHILD , 'A1' as PARENT , 1 as step union all
select 'Y' as CHILD , 'A2' as PARENT , 1 as step union all
select 'X' as CHILD , 'A3' as PARENT , 1 as step union all
select 'A1' as CHILD , 'B1' as PARENT , 2 as step union all
select 'A1' as CHILD , 'B2' as PARENT , 2 as step union all
select 'A1' as CHILD , 'B3' as PARENT , 2 as step union all
select 'A2' as CHILD , 'B4' as PARENT , 2 as step union all
select 'A2' as CHILD , 'B5' as PARENT , 2 as step union all
select 'A2' as CHILD , 'B6' as PARENT , 2 as step union all
select 'A3' as CHILD , 'B7' as PARENT , 2 as step union all
select 'A3' as CHILD , 'B8' as PARENT , 2 as step union all
select 'A3' as CHILD , 'B9' as PARENT , 2 as step 
)
select * FROM test_TBL 

base와 newer는 부모 자식 관계입니다.  step은 몇 번째 단계인가.. 하는 정보구요.

1스텝까지 역으로 조회해서 경로를 만드는 처리를 하고 싶습니다.

1스텝의 Z의 부모가 A이다. 하면 

2스텝에서 자식이 A인 경우는 현재 3개(B,C,D)가 있다할 경우

3가지 경우의 수가 있겠네요. 

CHILD와 PARENT가 있네요. 

저는 CHILD = 'Z' 에 관한 모든 가능한 부모 관계를 알고 싶습니다. 

예를 들면 CHILD가 Z이면 .. 먼저 1단계에 A1이 있네요. 여기에는 중복값이 없습니다. ..

2단계에서는 A1이 CHILD  가 됩니다. 

A1이 CHILD가 되는 경우는 B1,B2,B3 이렇게 3경우가 있네요.

그래서 풀어보면 

B1 > A1 > Z 

B2 > A1 > Z

B3 > A1 > Z

이 경우들이 있겠네요. 

해서 제가 원하는 결과는 

 

B1 > A1 > Z; B2 > A1 > Z; B3 > A1 > Z;

 

이런 결과입니다.  필요한것은 구분자로 구분된 문자열이지만 

 

B1 > A1 > Z ; 
B2 > A1 > Z ;
B3 > A1 > Z ;

이런 결과 셋으로 나와도 상관없을 것 같습니다. 

물론 step이 많아지면 계속 늘어나야지요.

여기서의 예는 2단계뿐이지만 저런식으로  PARENT가 CHILD가 되며 단계가 계속 올라갑니다.

10단계이상 올라갈 수 있구요.

 

경로만들기라고 제가 이름지었지만. 이런 처리를 뭐라고 하는지 잘 모르겠네요.   (계층구조쿼리의 역방향인거 같아요..)

 

쉬울줄알고 달려들었는데...

쉽지않네요. 

오라클 CONNECT_BY와 SYS_CONNECT_BY_PATH로 쉽게 될건데.. ㅠㅠ

sql server에서 with를 이용하여 connect_by와 비슷하게 처리할 수 있는 정보는 찾았으나

http://stackoverflow.com/questions/959804/simulation-of-connect-by-prior-of-oracle-in-sql-server

...

잘 안되네요. ㅠㅠ

프로시저로 가야할까요?

이게 또 에러인게..

테이블이 날짜 정보 붙어서 동적으로 생성되는 상황이라. 커서 도 동적 쿼리로 돌리고..

머리가 안돌아가서.. 핑계입니다. 

 

이거는 쿼리로 안되니.. 프로시저로 해라..라는 도움도 좋아요~~!!

그럼 도움 바랍니다. 

 

 

 

 

 

by 마농 [2014.07.16 08:53:47]

예시자료가 대표성을 가진 자료인가요?

2단계가 끝인지? 1레벨은 하나 뿐인지?


by 커피요쿠르트d [2014.07.16 09:30:27]

예. 질문하기 쉽게 저 자료만 보이게 만든겁니다. 

그리고 처음 쿼리 실행시 파라미터로 Z값을 받을 거라서요. 저렇게 표현이 되었네요.

그리고 단계는 계속 늘어날 수 있습니다.

1레벨은 많아요!! 

저거를 다시 표현하자면.. 역계층구조..라고 해야할거 같네요...

내가 스텝1인 BASE 하나를 던지면 

그 BASE가 맨 마지막에 오는 경로들을 찾고 싶은 거거든요.


by 마농 [2014.07.16 10:00:46]
WITH test_tbl (base, newer, step) AS
(
SELECT 'Z' base, 'A' newer, 1 step
UNION ALL SELECT 'A', 'B', 2
UNION ALL SELECT 'A', 'C', 2
UNION ALL SELECT 'A', 'D', 2
UNION ALL SELECT 'D', 'E', 3
)
, t1(base, newer, step, root, path) AS
(
SELECT base, newer, step
     , base root
     , CAST(newer + ' - ' + base AS VARCHAR(100)) path
  FROM test_tbl
 WHERE base = 'Z'
 UNION ALL
SELECT c.base, c.newer, c.step
     , p.root
     , CAST(c.newer + ' - ' + p.path AS VARCHAR(100)) path
  FROM test_tbl c, t1 p
 WHERE p.newer = c.base
)
SELECT REPLACE(
       (SELECT path + ' ; '
          FROM t1 a
         WHERE NOT EXISTS (SELECT 1 FROM t1 WHERE base = a.newer)
           FOR XML PATH('')
        ), '-', '>') path
;

 


by 커피요쿠르트d [2014.07.16 11:10:17]

정말 감사드립니다. 

감탄만 나오네요. 열을 문자열로 변환하는 처리도 잘 배우고 갑니다!!!

 

 


by 커피요쿠르트d [2014.07.16 14:58:42]

추가로 적자면...  
The maximum recursion 100 has been exhausted before statement completion 

에러메시지를 보신다면..

 무한루프에 빠지는 것을 막기 위해 기본 재귀호출 수가 정해져있나봐요..

옵션을 주면 무시 하고 실행 할 수 있습니다. 하지만.. 

데이터 건수가 좀.. 조금.. 많아지니..
쿼리가 끝나지를 않네요..  ㅜㅜ 
아.. 옵션입니다. 위 쿼리 바로 밑에 아래 코드를 추가하면 됩니다.

option (maxrecursion 0)

by 마농 [2014.07.17 09:37:26]

성능저하의 원인이???

1. 계층 구조 전개 때문인지?

2. Not Exists 사용 때문인지 체크해 보세요.

2번이 원인이라면 Not Exists 대신 셀프 아우터 조인후 널체크하는 방식으로 변경해 보세요.

 


by 커피요쿠르트d [2014.07.25 10:33:36]

댓글의 댓글이 안되는군요;;

마농님 지속적인 관심 감사합니다

인덱스를 안태워서 그런것이었어요....ㅠㅠ 죄송합니다;;ㅜㅜ

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