2012-01-16 2 views
5

현재 우리가있는 테이블에서 데이터를 반환하는 저장 프로 시저는 다음과 같이 수행하여 원래 스키마의 한 : 상관없이 테이블 스키마 변경, 거기만큼 방법 때문에,CTE 재귀 수준을 제한하는 방법은 일반 테이블을 선택 하시겠습니까?

WITH CTE AS 
(
    -- Start CTE off by selecting the id that was provided to stored procedure. 
    SELECT * 
    FROM [dbo].[TestTable] 
    WHERE [Id] = 1 
    -- Recursively add tasks that are children of records already found in previous iterations. 
    UNION ALL 
    SELECT t.* 
    FROM [dbo].[TestTable] as t 
    INNER JOIN CTE as tcte 
     ON t.[ParentId] = tcte.[Id] 
)   
SELECT * 
FROM CTE 

이것은 좋은입니다 [ Id] 및 [ParentId] 열에 대해서는이 저장 프로 시저를 업데이트하지 않아도됩니다. 비슷한 것을하고 싶지만 동적으로 재귀 깊이를 지정할 수도 있습니다. 이 작업을 수행하는 내가 본 유일한 방법은과 같이 레벨/깊이 식별자를 추가하는 것입니다

WITH CTE AS 
(
    -- Start CTE off by selecting the task that was provided to stored procedure. 
    SELECT *, 0 as [Level] 
    FROM [dbo].[TestTable] 
    WHERE [Id] = 1 
    -- Recursively add tasks that are children of parent tasks that have already been found in previous iterations. 
    UNION ALL 
    SELECT t.*, [Level] + 1 
    FROM [dbo].[TestTable] as t 
    INNER JOIN CTE as tcte 
     ON t.[ParentId] = tcte.[Id] 
    WHERE [Level] < 2 
)   
SELECT * 
FROM CTE 

이 잘 작동하지만 줄 것이다 끝에 *을 선택하기 때문에 이전 쿼리의 주요 플러스를 빼앗아 나도 수준. 레벨을 지정할 수있는 다른 방법이있을뿐만 아니라 테이블의 모든 열을 일반적으로 선택합니까? 미리 감사드립니다.

답변

12

당신이 당신의 수준 필드로 할 수있는 모든 제한은 재귀의 숫자이면, 당신은 MAXRECURSION query hint,이 같은 것을 사용할 수 있어야합니다 :

WITH Department_CTE AS 
(
    SELECT 
     DepartmentGroupKey, 
     ParentDepartmentGroupKey, 
     DepartmentGroupName 
    FROM dimDepartmentGroup 
    WHERE DepartmentGroupKey = 2 
    UNION ALL 
    SELECT 
     Child.DepartmentGroupKey, 
     Child.ParentDepartmentGroupKey, 
     Child.DepartmentGroupName 
    FROM Department_CTE AS Parent 
     JOIN DimDepartmentGroup AS Child 
      ON Parent.ParentDepartmentGroupKey = Child.DepartmentGroupKey 
) 
SELECT * FROM Department_CTE 
OPTION (MAXRECURSION 2) 

편집 :

대답에

로를 덧글에있는 질문, 아니, 당신은 MAXRECURSION 설정이 허용하는 것보다 더 많은 시간을 반복 할 때 당신이 얻는 오류를 억제 할 수 없습니다. 내가 제대로 이해하면, 당신이 뭔가를 할 수 있습니다 :

WITH CTE AS 
(
    -- Start CTE off by selecting the task that was provided to stored procedure. 
    SELECT Id, 0 as [Level] 
    FROM [dbo].[TestTable] 
    WHERE [Id] = 1 
    -- Recursively add tasks that are children of parent tasks that have already been found in previous iterations. 
    UNION ALL 
    SELECT t.Id, [Level] + 1 
    FROM [dbo].[TestTable] as t 
    INNER JOIN CTE as tcte 
     ON t.[ParentId] = tcte.[Id] 
    WHERE [Level] < 2 
), 
CTE2 AS 
(
    SELECT TestTable.* 
    FROM CTE 
     INNER JOIN TestTable ON CTE.Id = TestTable.Id 
) 
SELECT * FROM CTE2; 

이렇게하면 계층 또는 기본 키 필드를 변경 계획하지 않는 가정 위에있는 것과 똑같이 일반적인해야한다.

+0

한계에 도달하면 오류가 발생하는 것으로 보입니다. 거기에 MAXRECURSION 기반으로 중지 할 수있는 방법이 있지만 결과를 계속 사용할 수 있습니까? – Ocelot20

+0

위 답변 (다른 제안 사항 포함) ... – mwigdahl