2017-01-17 2 views
0

다음 표가 있습니다. 표 T1의 유형 열은 표 T2의 계층 구조를 따릅니다. 테이블 T1에 이름 당 유형을 나열하고 이름 당 리프를 찾고 싶습니다.계층 적 트리에서 그룹 당 리프 노드 찾기

 T1        T2 
name  type     type  parent 
----------------    -------------------- 
a1  person    | artist  person  
a1  artist    | actor  artist 
a2  person    | athlete person 
a2  athlete    | person  '' 
a3  person      
a3  artist     
a3  actor     

하지만이 출력 (그룹 이름 당 리프 노드)

a1  artist     
a2  athlete    
a3  actor 

을 찾고 여기

select a.* from T1 a left join T2 b on a.type = b.parent where b.parent is null; 
a2  athlete    
a3  actor 

를 작동하지 않을 이름 당 리프 노드를 찾을 수있는 일반적인 쿼리 즉, 이름마다 잎 노드를 찾고 싶으므로 a1의 경우 [사람, 아티스트]의 아티스트가 아티스트이고 a3 [사람, 아티스트, 배우]의 리프 노드는 배우가됩니다.
GROUP BY를 사용하여 원하는 출력 여기

+0

가장 먼 노드가 무엇을 의미하는지 명확하게 설명합니다. – DVT

+0

그냥 다시 썼습니다. 희망이 조금 더 명확합니다. – user1848018

+1

mysql 또는 sql-server입니까? 귀하의 질문에 둘 다 태그가 붙어 있습니다. –

답변

1

을 얻을 수있는 방법이 코드

WITH cte AS (
SELECT 
    t1.name AS anchor_name 
    , t1.type AS type 
    , t2.parent 
    , 0 AS level 
FROM #T1 t1 JOIN #T2 t2 ON t1.type = t2.type 

UNION ALL 

SELECT cte.anchor_name, cte.type, t2.parent, cte.level+1 
FROM cte JOIN #T2 t2 ON cte.parent = t2.type 
) 
, tmp AS (
    SELECT anchor_name, MAX(cte.level) AS max_level 
    FROM cte 
    GROUP BY cte.anchor_name 
) 
SELECT cte.anchor_name as name, cte.type 
FROM tmp JOIN cte ON cte.anchor_name = tmp.anchor_name AND cte.level = tmp.max_level 

이된다 그리고이 테스트 코드입니다 : 당신이 필요로하는

CREATE TABLE #T1 (
    name VARCHAR(2) 
    , type VARCHAR(MAX) 
    ); 

CREATE TABLE #T2 (
    type VARCHAR(MAX) 
    , parent VARCHAR(MAX) 
    ); 

INSERT INTO #T1 (name, type) 
VALUES 
('a1', 'artist') 
,('a1', 'person') 
,('a2', 'person') 
,('a2', 'athlete') 
,('a3', 'person') 
,('a3', 'artist') 
,('a3', 'actor'); 

INSERT INTO #T2 (type, parent) 
VALUES 
('artist' , 'person') 
,('actor'  , 'artist') 
,('athlete' , 'person') 
,('person' , ''); 


SELECT * 
FROM #T1; 

SELECT * 
FROM #T2; 

WITH cte AS (
    SELECT 
     t1.name AS anchor_name 
     , t1.type AS type 
     , t2.parent 
     , 0 AS level 
    FROM #T1 t1 JOIN #T2 t2 ON t1.type = t2.type 

    UNION ALL 

    SELECT cte.anchor_name, cte.type, t2.parent, cte.level+1 
    FROM cte JOIN #T2 t2 ON cte.parent = t2.type 
    ) 
, tmp AS (
    SELECT anchor_name, MAX(cte.level) AS max_level 
    FROM cte 
    GROUP BY cte.anchor_name 
) 
SELECT cte.anchor_name as name, cte.type 
FROM tmp JOIN cte ON cte.anchor_name = tmp.anchor_name AND cte.level = tmp.max_level 

http://rextester.com/TRD23741

+0

는 명확성을 위해 질문을 편집했습니다. 위 테이블은 훨씬 더 큰 테이블의 스냅 샷입니다. – user1848018

+0

@ user1848018 수정 된 답변 – DVT

관련 문제