2017-02-09 18 views
1

私はSQL Server 2008で作業しています。私の質問に対する答えは再帰的なCTEにあると思いますが、どのような解決策も高く評価されます。 sam_DB.dbo.exampleテーブルで再帰的CTEを使用したSQLグループ

PIDがnullでない場合、それは私が私の出力は、Aの各レコードを識別する新しいフィールド(CID)を持ちたいID

ID  | PID 
    ------ | ------ 
    1  | NULL 
    2  | 1  
    3  | 2  
    4  | 3  
    5  | NULL 
    6  | 5  
    7  | 6  
    8  | NULL 
    9  | NULL 
    10  | 9  

に戻ってリンクを下回ります以下のように、グループの一部としてPIDからIDへの連鎖の連鎖。

ID  | PID | CID 
    ------ | ------ | ------ 
    1  | NULL | 1  
    2  | 1  | 1  
    3  | 2  | 1  
    4  | 3  | 1  
    5  | NULL | 2  
    6  | 5  | 2  
    7  | 6  | 2  
    8  | NULL | 3  
    9  | NULL | 4  
    10  | 9  | 4  

答えて

0

あなたはROW_NUMBERウィンドウ機能により共通テキスト式を使用する必要が

CREATE TABLE #TblTemp(ID int,PID int) 


INSERT INTO #TblTemp(ID ,PID) VALUES (1,NULL),(2,1),(3,1),(4,3),(5,NULL),(6,5),(7,6),(8,NULL),(9,NULL),(10,9) 


;WITH CTE (ID, PID, CID) AS (

    SELECT ID, PID, ROW_NUMBER() OVER(ORDER BY ID) RN 
    FROM #TBLTEMP 
    WHERE PID IS NULL 

    UNION ALL 

    SELECT T.ID, T.PID, C.CID 
    FROM CTE C 
    INNER JOIN #TBLTEMP T 
    ON T.PID = C.ID 
) 
SELECT * 
FROM CTE 
ORDER BY ID 
1

これはCTEが必要なのは間違いありません。

あなたはトップレベルのレコード(つまり、親を持っていないもの)を選択するために、クエリの最初の部分を定義する必要があります。

select ID, PID, ID 
from @t 
where PID is null 

その後、すべての行が結果のCTEに追加された(つまり、最初の上記のクエリで返されたレコードのすべて、さらにクエリのこの2番目の部分で追加された新しい行ごとに、新しい追加が行われなくなるまで各追加ごとに繰り返されます)、親のIDを持つソーステーブルからすべてのレコードを追加する必要があります以前に追加された行のIDと一致します。別にこのロジックから

select t.ID, t.PID, c.CID 
from cte c 
inner join @t t 
on t.PID = c.ID 

、注意すべき唯一の他の事は最初の式のためのCID列は、それが親レコードのCIDをとる第二の式から返されたレコードの一方で、レコードのIDを取ることです。

完全なコード

--set up the demo data 
declare @t table (ID int not null, PID int null) 
insert @t 
values (1, null) 
, (2,1) 
, (3,2) 
, (4,3) 
, (5,null) 
, (6,5) 
, (7,6) 
, (8,null) 
, (9,null) 
, (10,9) 

--actual demo 
;with cte (ID, PID, CID) as (

    --select out top most (ancestor) records; setting CID to ID (since they're the oldest ancestor in their own chain, given they don't have parents) 
    select ID, PID, ID 
    from @t 
    where PID is null 

    union all 

    --select each record that is a child of the record we previously selected, holding the ancestor as the parent record's ancestor 
    select t.ID, t.PID, c.CID 
    from cte c 
    inner join @t t 
    on t.PID = c.ID 
) 
select * 
from CTE 
order by ID 
関連する問題