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
...
잘 안되네요. ㅠㅠ
프로시저로 가야할까요?
이게 또 에러인게..
테이블이 날짜 정보 붙어서 동적으로 생성되는 상황이라. 커서 도 동적 쿼리로 돌리고..
머리가 안돌아가서.. 핑계입니다.
이거는 쿼리로 안되니.. 프로시저로 해라..라는 도움도 좋아요~~!!
그럼 도움 바랍니다.
예시자료가 대표성을 가진 자료인가요?
2단계가 끝인지? 1레벨은 하나 뿐인지?
예. 질문하기 쉽게 저 자료만 보이게 만든겁니다.
그리고 처음 쿼리 실행시 파라미터로 Z값을 받을 거라서요. 저렇게 표현이 되었네요.
그리고 단계는 계속 늘어날 수 있습니다.
1레벨은 많아요!!
저거를 다시 표현하자면.. 역계층구조..라고 해야할거 같네요...
내가 스텝1인 BASE 하나를 던지면
그 BASE가 맨 마지막에 오는 경로들을 찾고 싶은 거거든요.
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)
성능저하의 원인이???
1. 계층 구조 전개 때문인지?
2. Not Exists 사용 때문인지 체크해 보세요.
2번이 원인이라면 Not Exists 대신 셀프 아우터 조인후 널체크하는 방식으로 변경해 보세요.
댓글의 댓글이 안되는군요;;
마농님 지속적인 관심 감사합니다
인덱스를 안태워서 그런것이었어요....ㅠㅠ 죄송합니다;;ㅜㅜ