2011-01-04 4 views
0

그룹 경로와 같은 빵 부스러기를 생성해야합니다.CTE - 역 계층

T_GROUP 저장 그룹의 실제 계층 구조 : 연락처에 속하는

GROUP_ID NAME   PARENT_ID LEVEL 
    7  g1    NULL   1 
    80 Workgroups  7   2 
    82 Advocacy  80   3 

T_CONTACT_GROUP 테이블에는 그룹 :

CONTACT_ID GROUP_ID 
55   82 
56   7 
55   7 

지금, 나는 접촉 아이디 55에 대한 을 다음과 같은 결과 집합 좀하고 싶습니다 : 연락처 55에 그룹 7도 할당되었으므로 g1이 예상 결과 집합에서 두 번 나타났습니다.

contactId GROUP_ID NAME PARENT_ID LEVEL 
55  7  g1  NULL  1 
55  80  g1|Workgroups 7 2 
55  82  g1|Workgroups|Advocacy 80 3 
55  7   g1 NULL 1 

답변

2

최소한 두 가지 방법이 있습니다. 제목에서 CTE를 언급 했으므로 먼저 CTE를 살펴 보겠습니다. 링크 here에서 은 내가 hiererchical CTE, 약간의 마사지의 예를 가지고 있고 그것은 아이들보다는 부모를 나타냅니다 :

WITH Hierarchy (Group_ID, Name, Parent_ID, Level) AS 
(
    SELECT Group_ID, Name, Parent_ID, Level 
    FROM T_Group 
    WHERE Contact_id = @Leaf 
UNION ALL 
    SELECT g.Group_ID, g.Name, g.Parent_ID, g.Level 
    FROM T_Group g 
    INNER JOIN Hierarchy h ON g.Group_ID = h.Parent 
) 
이 CTE는 저장 프로 시저 또는 테이블 사용자 정의 함수에 배치 될

복용 @Leaf의 매개 변수 (사용자가 찾고있는 리프 노드. 예에서는 82와 7).

이 문제는 계층적인 CTE가 매우 비싸고, 특히 깊은 트리 구조에서 작업하거나 반복적으로 호출하는 경우 비용이 많이 올 수 있다는 점입니다. 캐싱이 도움이 될 수 있지만 다른 옵션이 있습니다.

또 다른 방법은 그룹과 함께 문자열 연결된 필드에 부모의 계층 구조를 저장하는 것입니다 :

GROUP_ID NAME  PARENT_ID LEVEL PARENTS 
82  Advocacy 80  3  |7|80|82| 

당신은 다음과 같이 할 수있다 :

SELECT p.Group_ID, g.Name, g.Parent_ID, g.Level 
FROM T_GROUP g 
CROSS JOIN dbo.StringSplit('|', Parents) p 
WHERE p.Value = g.Group_ID 

는 모든 세부 사항을 얻는을 부모님. 이는 조회 처리를 위해 CTE를 사용하는 것보다 훨씬 효율적입니다. GROUP에 새로운 레코드를 삽입 할 때 부모 필드도 반드시 만들어야한다는 것을 의미합니다. 일반적으로 이것을 처리하기 위해 필요에 따라 부모를 구성하여 그룹을 만든 저장 프로 시저를 만듭니다.