2017-01-17 24 views
0

次の表があります。表T1のタイプ列は、表T2の階層に従います。私はテーブルT1の名前ごとのタイプをリストし、名前ごとにリーフを見つけたいと思います。階層ツリーのグループごとに葉ノードを見つける

名あたりのリーフ・ノードを見つけるために、通常のクエリはここ

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

動作しないでしょう

 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 

を探しています言い換えれば、名前ごとに葉ノードを探したいので、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

関連する問題