2017-01-25 10 views
0

MSSQLを使用して、親の子関係を持つテーブルをトラバースしようとしています。最後の葉まで、適切なインデントされた方法ですべての要素を取得するように、結果セットが必要です。それらにMSSQLの再帰的階層トラバーサル

親項目36は、これらの子供17と18の2人の子供17と18のそれぞれ1人の以上の子を持っている26、42それぞれ

36 - 17 
17 - 26 
36 - 18 
18 - 42 

しかし、私の再帰は、データの観点からOK取り組んでいますトラバース、しかし賢明な順序、それは失敗しています。私の再帰クエリは私に次のような出力

36 - 17 
36 - 18 
17 - 26 
18 - 42 

を与えるそれから、それらのレベルの子供のそれぞれを横断、記録に格納し、一度にすべてのレベルをもたらします。

Oracleの「connect by prior」は正常に動作しているようですが、MSSQLはありません。私は

WITH SRC (Level, PARITEMID, CHIITEMID) AS 
    (
    SELECT 
     0 as Level, 
     PI.pitem_id as PARITEMID, 
     CI.pitem_id as CHIITEMID 
    FROM PI, CI JOIN <Condition> where PI.PITEM_ID = 

    UNION ALL 

    SELECT 
     Level + 1, 
     PI1.pitem_id as PARITEMID, 
     CI1.pitem_id AS CHIITEMID 
     FROM PI1, CI1 JOIN <Condition> 
) 
Select * from SRC 

を使用しています何のサンプルを貼り付けています、私はそれを注文して入手SRCに行う必要があるものはあり、または基本的に再帰自体に問題があるのですか?私は次のことを想定して

+0

にすることで、最終的な順序を設定しますが、最終的な結果セットの特定の順序が必要な場合は、 '指定する必要があります。 ORDER BY'である。 'ORDER BY'節がなければ、結果セット内の行は任意の順序で返されます。 –

+0

親子関係です。私が前もって指定できる順序はありません。葉まで各階層を得ることができる実行可能なORDERを提案できますか? – Srikanth

+1

いくつかのサンプルデータを提供する場合は(好ましくは、十二行で十分です)、好ましくは 'CREATE TABLE'と' INSERT'文の形式でクエリの期待される結果、あなたはかなり良い答えを得るでしょう。また、使用するSQL Serverのバージョンのタグを追加すると役立ちます。 –

答えて

2

は、あなたのフィールド名に明確ではありませんでした:

cItem_ID - 子供のID pItem_ID - 親ID ITEM_TITLE - また、項目名/説明

、シーケンス上の明確ではありません、そこで私はItem_Title(アルファベット順)を前提としました。ただし、使用可能なフィールドはすべて使用できます。 ( "10000 + Row_Number()"行参照)

cteR1とcteR2は必要ありません。私は範囲キーが好きです、彼らは多くの目的のサーバーです。あなたがそれらを削除した場合は、単にいつものようにOrder By A.Seq

Declare @MyTable table (pItem_ID int,cItem_ID int,item_Title varchar(50)) 
Insert into @MyTable values 
(null,36,'Item 36') 
,(36,17,'Item 17') 
,(17,26,'Item 26') 
,(36,18,'Item 18') 
,(18,42,'Item 42') 


Declare @Top int   = null  --<< Sets top of Hier Try 7 
Declare @Nest varchar(25) = '|-----' --<< Optional: Added for readability 

;with cteP as (
     Select Seq = cast(10000+Row_Number() over (Order by item_Title) as varchar(500)) 
      ,cItem_ID 
      ,pItem_ID 
      ,Lvl=1 
      ,item_Title 
     From @MyTable 
     Where IsNull(@Top,-1) = case when @Top is null then isnull(pItem_ID,-1) else cItem_ID end 
     Union All 
     Select Seq = cast(concat(p.Seq,'.',10000+Row_Number() over (Order by r.item_Title)) as varchar(500)) 
      ,r.cItem_ID 
      ,r.pItem_ID 
      ,p.Lvl+1 
      ,r.item_Title 
     From @MyTable r 
     Join cteP p on r.pItem_ID = p.cItem_ID) 
    ,cteR1 as (Select *,R1=Row_Number() over (Order By Seq) From cteP) 
    ,cteR2 as (Select A.Seq,A.cItem_ID,R2=Max(B.R1) From cteR1 A Join cteR1 B on (B.Seq like A.Seq+'%') Group By A.Seq,A.cItem_ID) 
Select A.R1 
     ,B.R2 
     ,A.cItem_ID 
     ,A.pItem_ID 
     ,A.Lvl 
     ,item_Title = Replicate(@Nest,A.Lvl-1) + A.item_Title 
From cteR1 A 
Join cteR2 B on A.cItem_ID=B.cItem_ID 
Order By A.R1 

戻り

enter image description here

+0

ありがとう、それは順序とそれに基づいてソートを追跡する良い方法です。それは働いた – Srikanth

+0

@Srikanth幸せそれは助けた。 –

関連する問題