MSSQL CTE 재귀, 트리구조 쿼리구현
mssql recursive cte ( oracle start with ... connect by ... )
재귀적 CTE 구조 (SQL Server 2005 온라인 설명서)
의사 코드 및 의미 체계
/ddue.schemas.microsoft.com/authoring/2003/5:content xmlns="http://ddue.schemas.microsoft.com/authoring/2003/5">
재귀적 CTE 구조에는 앵커 멤버와 재귀 멤버가 적어도 하나씩 포함되어야 합니다. 다음 의사 코드에서는 단일 앵커 멤버와 단일 재귀 멤버가 포함된 간단한 재귀적 CTE의 구성 요소를 보여 줍니다.
WITH cte_name ( column_name [,...n] )
AS
(
CTE_query_definition –- Anchor member is defined.
UNION ALL
CTE_query_definition –- Recursive member is defined referencing cte_name.
)
-- Statement using the CTE
SELECT *
FROM cte_name
재귀 실행의 의미 체계는 다음과 같습니다.
- CTE 식을 앵커 멤버와 재귀 멤버로 분할합니다.
- 앵커 멤버를 실행하여 첫 번째 호출 또는 기본 결과 집합(T0)을 만듭니다.
- Ti는 입력으로 사용하고 Ti+1은 출력으로 사용하여 재귀 멤버를 실행합니다.
- 빈 집합이 반환될 때까지 3단계를 반복합니다.
- 결과 집합을 반환합니다. 이것은 T0에서 Tn까지의 UNION ALL입니다.
--------------------------------------------------------------------------------------------
예)
create table test_rcte
(
idx int,
p_idx int,
val varchar(10)
);
insert into test_rcte(idx, p_idx, val) values (1, null, 'root');
insert into test_rcte(idx, p_idx, val) values (2, 1, 'user1');
insert into test_rcte(idx, p_idx, val) values (3, 1, 'user2');
insert into test_rcte(idx, p_idx, val) values (4, 1, 'user3');
insert into test_rcte(idx, p_idx, val) values (5, 2, 'user4');
insert into test_rcte(idx, p_idx, val) values (6, 2, 'user5');
insert into test_rcte(idx, p_idx, val) values (7, 3, 'user6');
insert into test_rcte(idx, p_idx, val) values (8, 3, 'user7');
insert into test_rcte(idx, p_idx, val) values (9, 4, 'user8');
insert into test_rcte(idx, p_idx, val) values (10, 5, 'user9');
insert into test_rcte(idx, p_idx, val) values (11, 5, 'user10');
insert into test_rcte(idx, p_idx, val) values (12, 6, 'user11');
insert into test_rcte(idx, p_idx, val) values (13, 6, 'user12');
insert into test_rcte(idx, p_idx, val) values (14, 7, 'user14');
insert into test_rcte(idx, p_idx, val) values (15, 7, 'user15');
insert into test_rcte(idx, p_idx, val) values (16, 8, 'user16');
insert into test_rcte(idx, p_idx, val) values (17, 8, 'user17');
insert into test_rcte(idx, p_idx, val) values (18, 10, 'user18');
| MSSQL | val | lvl | ORACLE | val | lvl | |
| root | 1 | root | 1 | |||
| user1 | 2 | user1 | 2 | |||
| with cte (val, p_idx, idx, lvl) | user2 | 2 | select val, level as lvl | user3 | 2 | |
| as | user3 | 2 | from test_rcte | user2 | 2 | |
| ( | user8 | 3 | start with p_idx is null | user6 | 3 | |
| select val, p_idx, idx, 1 as lvl | user6 | 3 | connect by prior idx = p_idx | user4 | 3 | |
| from test_rcte | user7 | 3 | order by level; | user7 | 3 | |
| where p_idx is null | user4 | 3 | user8 | 3 | ||
| union all | user5 | 3 | user5 | 3 | ||
| select a.val, a.p_idx, a.idx, lvl + 1 | user11 | 4 | user17 | 4 | ||
| from test_rcte a, cte b | user12 | 4 | user16 | 4 | ||
| where a.p_idx = b.idx | user9 | 4 | user14 | 4 | ||
| ) | user10 | 4 | user15 | 4 | ||
| select val, lvl from cte | user16 | 4 | user12 | 4 | ||
| order by lvl | user17 | 4 | user11 | 4 | ||
| user14 | 4 | user9 | 4 | |||
| user15 | 4 | user10 | 4 | |||
| user18 | 5 | user18 | 5 |
| MSSQL | val | lvl | path |
| root | 1 | / root | |
| with cte (val, p_idx, idx, lvl, path) | user1 | 2 | / root / user1 |
| as | user2 | 2 | / root / user2 |
| ( | user3 | 2 | / root / user3 |
| select val, p_idx, idx, 1 as lvl, convert(varchar(100), ' / ' + val) path | user8 | 3 | / root / user3 / user8 |
| from test_rcte | user6 | 3 | / root / user2 / user6 |
| where p_idx is null | user7 | 3 | / root / user2 / user7 |
| union all | user4 | 3 | / root / user1 / user4 |
| select a.val, a.p_idx, a.idx, lvl + 1, convert(varchar(100), path + ' / ' + a.val) | user5 | 3 | / root / user1 / user5 |
| from test_rcte a, cte b | user11 | 4 | / root / user1 / user5 / user11 |
| where a.p_idx = b.idx | user12 | 4 | / root / user1 / user5 / user12 |
| ) | user9 | 4 | / root / user1 / user4 / user9 |
| select val, lvl, path from cte | user10 | 4 | / root / user1 / user4 / user10 |
| order by lvl | user16 | 4 | / root / user2 / user7 / user16 |
| user17 | 4 | / root / user2 / user7 / user17 | |
| user14 | 4 | / root / user2 / user6 / user14 | |
| user15 | 4 | / root / user2 / user6 / user15 | |
| user18 | 5 | / root / user1 / user4 / user9 / user18 | |
| ORACLE | val | lvl | path |
| root | 1 | / root | |
| select val, level as lvl, sys_connect_by_path(val,' / ') path | user1 | 2 | / root / user1 |
| from test_rcte | user3 | 2 | / root / user3 |
| start with p_idx is null | user2 | 2 | / root / user2 |
| connect by prior idx = p_idx | user6 | 3 | / root / user2 / user6 |
| order by level; | user4 | 3 | / root / user1 / user4 |
| user7 | 3 | / root / user2 / user7 | |
| user8 | 3 | / root / user3 / user8 | |
| user5 | 3 | / root / user1 / user5 | |
| user17 | 4 | / root / user2 / user7 / user17 | |
| user16 | 4 | / root / user2 / user7 / user16 | |
| user14 | 4 | / root / user2 / user6 / user14 | |
| user15 | 4 | / root / user2 / user6 / user15 | |
| user12 | 4 | / root / user1 / user5 / user12 | |
| user11 | 4 | / root / user1 / user5 / user11 | |
| user9 | 4 | / root / user1 / user4 / user9 | |
| user10 | 4 | / root / user1 / user4 / user10 | |
| user18 | 5 | / root / user1 / user4 / user9 / user18 |
'프로그래밍 > 디비' 카테고리의 다른 글
| hbase 세컨더리 인덱스 (0) | 2011/07/07 |
|---|---|
| 아파치 카산드라와 솔라의 결합 솔란드라 (Solandra) (cassandra+solr) (0) | 2011/02/09 |
| MSSQL CTE 재귀, 트리구조 쿼리구현 (1) | 2009/04/23 |
| 정규식을 활용한 손쉬운 패턴 검색 및 데이터 추출 (0) | 2009/01/20 |
| 우편번호 jsp asp php 데이터베이스(mysql 오라클 mssql) 개발 (1) | 2008/01/22 |
| 하이버네이트로 추출이 가능한 이클립스 디비플러그인 (0) | 2008/01/03 |

댓글을 달아 주세요
너무나 좋은 소스 고맙습니다.
참고 하겠습니다.