2016-10-12 2 views
1
FromID    ToID  
-------------- ----------  
    1    2    
    2    3     
    3    4     
    5    6     
    6    7     
    9    10 
내가

SQL 서버 2008 재귀 쿼리

FromID    Path 
1      1,2,3,4 
5      5,6,7           
9      9,10 

내가 사용 아래 온라인 예를 참조하는 SQL 문을 구성하기 위해 노력 해왔다 같은 출력을 생성하는 SQL Server 2008의 재귀 쿼리를 사용하고 싶습니다

;WITH items AS (
    SELECT FromID 
    , CAST(FromID AS VARCHAR(255)) AS Path 
    FROM tablex 
    UNION ALL 
    SELECT i.FromID 
    , CAST(Path + '.' + CAST(i.FromID AS VARCHAR(255)) AS VARCHAR(255)) AS Path 
    FROM tablex i 
    INNER JOIN items itms ON itms.FromID = i.ToID 
) 
SELECT * 
FROM items 
ORDER BY Path 

그러나 위의 방법은 작동하지 않습니다. 어떤 아이디어?

+0

따라서 2-3가 자신의 행을 얻을 수 없겠죠하지만 6-9 이전에 6-7했다 때문? –

+0

안녕하세요, 간단히 말해서, 나는 6-9을 꺼 냈습니다. 그것은 1,5,9가 루트 ID 인 트리 구조와 같습니다. 루트 ID마다 아이들이 필요합니다. – user3050151

답변

1

예상되는 출력이 왜 그런지는 분명하지 않습니다. 6-10의 경로는 10의 완전한 경로가 아니며 ID 5에서 시작됩니다. 전체 경로를 출력하는 예제를 작성하여이를 수행하는 방법을 설명합니다. 어떤 이유로 든 6에서 시작하기를 원한다면 결과 집합에 시작점으로 표시 할 노드를 결정하는 규칙을 명확하게 지정하십시오.

샘플 데이터의 모든 ID는 전임자가 정확히 하나이지만 후임이 잠재적으로 여러 개인 것으로 나타났습니다. 그런 이유로 저는 엔드 포인트 인 노드를 확인한 다음 시작 지점으로 거꾸로 작업합니다. 아래의 코드 주석은 나머지 부분을 설명하기에 충분합니다.

declare @TableX table (FromID int, ToID int); 
insert @TableX values (1, 2), (2, 3), (3, 4), (5, 6), (6, 7), (6, 9), (9, 10); 

with PathCTE as 
(
    -- BASE CASE 
    -- Any ID that appears as a "to" but not a "from" is the endpoint of a path. This 
    -- query captures the ID that leads directly to that endpoint, plus the path 
    -- represented by that one row in the table. 
    select 
     X1.FromID, 
     [Path] = convert(varchar(max), X1.FromID) + ',' + convert(varchar(max), X1.ToID) 
    from 
     @TableX X1 
    where 
     not exists (select 1 from @TableX X2 where X2.FromID = X1.ToID) 

    union all 

    -- RECURSIVE CASE 
    -- For every path previously identified, look for another record in @TableX that 
    -- leads to its starting point and prepend that record's from ID to the overall path. 
    select 
     X.FromID, 
     [Path] = convert(varchar(max), X.FromID) + ',' + PathCTE.[Path] 
    from 
     PathCTE 
     inner join @TableX X on PathCTE.FromID = X.ToID 
) 

-- Any ID that appears as a "from" but not a "to" is the starting point of one or more 
-- paths, so we get all results beginning at one of those points. All other output from 
-- PathCTE is partial paths, which we can ignore. 
select * 
from 
    PathCTE 
where 
    not exists (select 1 from @TableX X where PathCTE.FromID = X.ToID) 
order by 
    FromID, [Path]; 

출력 :

FromID Path 
1  1,2,3,4 
5  5,6,7 
5  5,6,9,10 
+0

고마워요. 나는 내 질문을 단순화하려고 노력했다. 나는 실제로 2 개의 테이블을 가지고있다. 두 번째 테이블에는 각 노드의 좌표가 있습니다. 예 : 1-coords1, 2-coords2, 3-coords3, 4-coords4 등을 기록합니다. 또한 'Path'필드가 좌표를 반환하는 출력으로 끝나기 위해 2 테이블을 조인해야합니다. – user3050151

+0

@ user3050151 : 위 질문에서 CTE 안에있는 두 개의 'select'문 각각을 간단히 수정해야하는 것 같습니다. 각'from' 절을'@ TableX'에서 두 번째 테이블로 조인 한 다음'[Path]'의 정의를 수정하여'X.FromID' 대신 두 번째 테이블의 해당 필드를 사용하십시오. –