2011-12-13 2 views
0

안녕하세요. 내 범주의 전체 계층 구조를 가져 오려고합니다. 다음은 아이디 볼 수 있듯이 CTE 출력이SQL CTE를 사용하여 전체 계층 구조를 얻는 방법

ID  PARENT_ID  NAME 
--------------------------- 
1  NULL   A    
2  NULL   B    
3  NULL   C    
4  1    D    
5  4    E    
5  1    E 

을해야

ID  PARENT_ID  NAME   DEPTH 
------------------------------------------ 
1  NULL   A    1 
2  NULL   B    1 
3  NULL   C    1 
4  1    D    2 
5  4    E    3 

내 샘플 테이블 : 5 내가 전체 트리를 조회하려면 어떻게 4의 부모와 1 인은

답변

2
DECLARE @tmp TABLE(ID INT,ParentID INT,NAME VARCHAR(10),DEPTH INT) 

INSERT INTO @tmp VALUES 
(1  ,NULL   ,'A'    ,1), 
(2  ,NULL   ,'B'    ,1), 
(3  ,NULL   ,'C'    ,1), 
(4  ,1    ,'D'    ,2), 
(5  ,4    ,'E'   ,3), 
(6  ,5    ,'F'   ,4); 

select * from @tmp 

;WITH cte AS 
(
    SELECT A.ID 
      ,A.ParentID 
      ,A.NAME 
      ,A.DEPTH 
    FROM @tmp A 

    UNION ALL 

    SELECT A.ID 
      ,B.ParentID 
      ,A.NAME 
      ,A.DEPTH 
    FROM cte A 
    INNER JOIN @tmp B on A.ParentID = B.ID 
    WHERE B.ParentID IS NOT NULL 

) 

SELECT * FROM cte 
+0

고맙습니다. – Luke101

+0

같은 깊이에 둘 이상의 행이있을 경우 쿼리가 작동하지 않습니다. 즉, 깊이 3에 부모 4가있는 행이 세 개 더있는 경우 쿼리가 작동하지 않습니다. – Asher

+0

안녕하세요. 이 주제에 관한 질문 : http://stackoverflow.com/a/8517097/184773. 너 나 한테 그것을 확인할 수 있니? 나는 당신이 SQL 서버에 대해 매우 knowledgable다는 것을 알 수 있습니다. – Luke101

1

SQL Server 2008에서 CTE는 재귀 적으로 쿼리하는 데 사용할 수 있습니다. MSDN

에서 CTE의

예 - 샘플 솔루션 (안된)는

;With TableCTE(Id, Name, ParentId, Depth) 
(
    Select ID,Name,ParentId, 1 
    FROM MyTable 

    Union All 

    Select C.Id, C.Name, t.ParentId, c.Depth +1 
    FROM @tmp t 
    INNER JOIN TableCTE C on t.Id = c.ParentId 
    -- Where t.ParentId IS Not Null 
) 

SELECT Id, Name, ParentId 
FROM TableCTE 
+0

나는이 시도하지만, 그 ID를 반환하지 않았습니다 : 5 ID의 부모입니다 : 1 – Luke101

+0

CTE 루프는 모든 행을 반환 할 때까지 반복적으로 반복되므로 루프를 되돌리려면 쿼리를 수정해야합니다. 업데이트 된 답변을 참조하십시오. –

+0

'Where t.ParentId IS NOT NULL'절을 제거하여 잘못된 결과를 얻었습니다. 즉 깊이 1과 2는 모두 깊이 1로 간주되고 후속 깊이는 1보다 작습니다. –

0
;WITH cte AS 
(
    SELECT A.ID 
      ,A.ParentID 
      ,A.NAME 
      ,A.DEPTH 
    FROM @tmp A 
    WHERE A.ParentID IS NULL 

    UNION ALL 

    SELECT B.ID 
      ,B.ParentID 
      ,B.NAME 
      ,B.DEPTH 
    FROM cte A 
       INNER JOIN 
      @tmp B on B.ParentID = A.ID 
    WHERE B.ParentID IS NOT NULL 

) 

SELECT * FROM cte