2010-03-02 6 views
5

표현 만 선택 노드 :재귀 쿼리 - 잎 노드가 활성 데이터는 다음 재귀 쿼리 감안할 때

WITH DepartmentHierarchy (DepartmentID, Name, IsInactive, IsSpecial, ParentId, HierarchyLevel) AS 
(
    -- Base case 
    SELECT 
     DepartmentId, 
     Name, 
     IsInactive, 
     IsSpecial, 
     ParentId, 
     1 as HierarchyLevel 
    FROM StoreDepartment 
    WHERE ParentId IS NULL 

    UNION ALL 

    -- Recursive step 
    SELECT 
     d.DepartmentId, 
     d.Name, 
     d.IsInactive, 
     d.IsSpecial, 
     d.ParentId, 
     dh.HierarchyLevel + 1 AS HierarchyLevel 
    FROM StoreDepartment d 
     INNER JOIN DepartmentHierarchy dh ON 
     d.ParentId = dh.DepartmentId 
) SELECT * FROM DepartmentHierarchy 

I는 다음과 같습니다 데이터를 선택할 수 있어요 : 또한

DepartmentId, Name, IsInactive, IsSpecial, ParentId, HeirarchyLevel 
1, Store, 0, 0, NULL, 1 
2, Main Department 1, 0, 1, 2 
3, Main Department 2, 0, 1, 2 
4, Sub For Main 1, 0, 2, 3 

을하는 가정 DepartmentId 및 ItemId (예 : DepartmentItemRelationship)가있는 테이블이 있습니다. 부서 계층의 리프 노드는 여기의 항목과 쌍을 이룹니다.

부서/항목 관계 테이블에서 일치 항목이있는 노드가 하나 이상있는 노드 (모든 수준에서) 만 반환하도록 내 재귀 쿼리를 원합니다. 이 노드는 6 ~ 7 단계까지 내려갈 수 있으므로 포함시킬 수 있도록 내 쿼리를 어떻게 수정해야하는지 잘 모르겠습니다.

덕분에, 카일

+0

카일, 레벨 6의 요구 사항을 충족하는 리프 노드가있는 경우 해당 노드 위의 5 개 부서를 표시 하시겠습니까? –

답변

3

당신은 계층 구조를 추적 경로 열을 만들 수 있습니다. 그런 다음 DepartmentItemRelationship 테이블에 일치하는 자식 노드 만 추가 할 수 있습니다. 그리고 마침내 적어도 자식이있는 노드 만 얻으십시오. 이 같은

시도 뭔가 :

WITH DepartmentHierarchy (DepartmentID, Name, IsInactive, IsSpecial, ParentId, HierarchyLevel) AS 
(
    -- Base case 
    SELECT 
     '/'+cast(DepartmentId as varchar(max)) as [path] 
     DepartmentId, 
     Name, 
     IsInactive, 
     IsSpecial, 
     ParentId, 
     1 as HierarchyLevel 
    FROM StoreDepartment 
    WHERE ParentId IS NULL 

    UNION ALL 

    -- Recursive step 
    SELECT 
     dh.[path] +'/'+ cast(d.DepartmentId as varchar(max)) as [path] 
     d.DepartmentId, 
     d.Name, 
     d.IsInactive, 
     d.IsSpecial, 
     d.ParentId, 
     dh.HierarchyLevel + 1 AS HierarchyLevel 
    FROM StoreDepartment d 
     INNER JOIN DepartmentHierarchy dh ON 
     d.ParentId = dh.DepartmentId 
    where exists (select top 1 1 
        from DepartmentItemRelationship di 
        where di.DepartmentId = d.DepartmentId) 
) 
SELECT * 
FROM DepartmentHierarchy dh 
where exists (select top 1 1 
       from DepartmentHierarchy 
       where charindex('/'+dh.DepartmentID+'/',[path]) > 0) 
+0

이것은 훌륭하게 작동합니다. 나무를 가로 지르는 길을 걷는 것만으로도 어떤 기록을 되 찾을 지 결정하는 데 도움이 될 것입니다. (참고 : 재귀 쿼리에서 허용되지 않았기 때문에 'TOP'절을 제거했습니다.) –

1

내가 제대로 이해하면, 당신은 리프 수준 위의 정확히 한 수준의 모든 노드를 원하는?

실제로 재귀 쿼리가 필요하지 않습니다. 먼저 잎 노드를 찾은 다음 부모를 모두 선택하면됩니다.

WITH LeafNodeParents AS 
(
    SELECT DISTINCT ParentId 
    FROM StoreDepartment 
    WHERE DepartmentId NOT IN 
    (
     SELECT DISTINCT ParentId FROM StoreDepartment 
    ) 
) 
SELECT d.DepartmentId, d.Name, d.IsInactive, d.IsSpecial, d.ParentId 
FROM LeafNodeParents p 
INNER JOIN StoreDepartment d 
    ON d.DepartmentId = p.ParentId 

유일한 단서는 레벨입니다. 얼마나 심하게 당신이 그것을 필요로하는지 잘 모르겠습니다. 그렇지 않은 경우 재귀 버전보다 더 나은 성능을 발휘해야합니다. 그렇게한다면 Jose의 쿼리가 괜찮은 것 같습니다 (빠른 눈으로 판단).

+0

제안을 주셔서 감사합니다. 모든 노드에서 데이터를 얻을 수 있기 때문에 다른 대답을 수락했습니다. 나는 아직도 당신의 대답에 감사하고 (그리고 upvoted). –