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
...
잘 안되네요. ㅠㅠ
프로시저로 가야할까요?
이게 또 에러인게..
테이블이 날짜 정보 붙어서 동적으로 생성되는 상황이라. 커서 도 동적 쿼리로 돌리고..
머리가 안돌아가서.. 핑계입니다.
이거는 쿼리로 안되니.. 프로시저로 해라..라는 도움도 좋아요~~!!
그럼 도움 바랍니다.
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 ;
추가로 적자면...
The maximum recursion 100 has been exhausted before statement completion
에러메시지를 보신다면..
무한루프에 빠지는 것을 막기 위해 기본 재귀호출 수가 정해져있나봐요..
옵션을 주면 무시 하고 실행 할 수 있습니다. 하지만..
데이터 건수가 좀.. 조금.. 많아지니..
쿼리가 끝나지를 않네요.. ㅜㅜ
아.. 옵션입니다. 위 쿼리 바로 밑에 아래 코드를 추가하면 됩니다.
option (maxrecursion 0)