2009-09-04 22 views
4

Iは、次の階層のテーブルを持っている:このheirarchicalテーブルをフラットテーブルに非正規化する最も簡単で簡単な方法は何ですか?

Table Category: 
CategoryId, ParentCategoryId, CategoryName 
1, null, SomeRoot 
2, 1, SomeChild 
3, 2, SomeGrandchild 
4, 3, SomeGreatGrandchild 

(このサンプルデータはレベル4より前のノード上の葉を含まないが、それが可能であることに注意)。データが関連する場合、データはレベル4より深くなることはありません。私は変換したい/このピボットは、固定4レベル私が使用するレベルを検出するための巨大なcase文をカテゴリテーブルに4回参加外側左、そして建てやった

CatId, Name1, Name2, Name3, Name4 
1, SomeRoot, null, null, null 
2, SomeRoot, SomeChild, null, null 
3, SomeRoot, SomeChild, SomeGrandchild, null 
4, SomeRoot, SomeChild, SomeGrandchild, SomeGreatGrandchild 

表示IDフィールドが、それはnullの行が含まれていません....任意のアイデア?助けて!

+1

データのレベルが常に jcollum

+1

@jcollum Updated Q:関連性がある場合、データはレベル4より深くなることはありません。 – TheSoftwareJedi

+1

再帰レベルが不明な場合は、CTEを使用します。知られているレベルと小さいレベルの再帰については、CTEにオーバーヘッドが多く、サブクエリが優れていると聞きました。 – jcollum

答えて

0

これを試してみてください:年のコメントに基づいて

Select C.CatId, C.Name, PC.Name, GP.Name, GGP.Name 
    From Category C 
    Left Join Category PC On PC.CatId = C.ParentCategoryId 
    Left Join Category GP On GP .CatId = PC.ParentCategoryId 
    Left Join Category GGP On GGP .CatId = GP.ParentCategoryId 

、次のようにUDFを作成する場合:

Create Function CatParentNames 
(@CatId Integer) 
Returns varchar(1000) 
AS 
Begin 
    Declare @outVal VarChar(1000) 
    Declare @ParId Integer 
    Select @ParId = ParentCategoryId, @outVal = Name 
    From Category 
    Where CatId = @CatId 
    While Exists(Select * From Category 
        Where CatId = @ParId) 
     Begin 
      Select @ParId = ParentCategoryId, 
       @outVal = Name + ', ' + @outVal 
      From Category 
      Where CatId = @ParId 
     End 

Return @outVal 

End 

を、その後、次のようにSQLを記述します。

Select CatId, dbo.CatParentNames(CatId) 
From Category 
Where ParentCategoryId Is Not Null 
+0

私はそれを元々持っていましたが、 "どこにC.parentcategoryidがヌルである"として、ルートから外していました。しかし、この例では、1つの結果しか返しません。また、Idはルートの – TheSoftwareJedi

+0

where節なしで試してみるでしょうか?原因where節は、唯一のルートレコード(それはnullのparentCatIdを持つ唯一のものです)に制限します。 –

+0

私が書いたやり方では、Categoryテーブルのすべての行が返される必要があります。すべての外部結合.... –

0

てみてくださいこれは:

select a.CategoryId as CatId, 
a.CategoryName as Name1, 
cast(null as varchar(20)) as Name2, 
cast(null as varchar(20)) as Name3, 
cast(null as varchar(20)) as Name4 
from @YourTable a 
where a.ParentCategoryId is null 

union all 

select b.CategoryId, 
a.CategoryName, 
b.CategoryName, 
null, 
null 
from @YourTable a 
inner join @YourTable b 
on a.CategoryId = b.ParentCategoryId 
where a.ParentCategoryId is null 


union all 

select c.CategoryId, 
a.CategoryName, 
b.CategoryName, 
c.CategoryName, 
null 
from @YourTable a 
inner join @YourTable b 
on a.CategoryId = b.ParentCategoryId 
inner join @YourTable c 
on b.CategoryId = c.ParentCategoryId 
where a.ParentCategoryId is null 

union all 

select d.CategoryId, 
a.CategoryName, 
b.CategoryName, 
c.CategoryName, 
d.CategoryName 
from @YourTable a 
inner join @YourTable b 
on a.CategoryId = b.ParentCategoryId 
inner join @YourTable c 
on b.CategoryId = c.ParentCategoryId 
inner join @YourTable d 
on c.CategoryId = d.ParentCategoryId 
order by 2, 3, 4, 5 

しかし、あなたはこのようになり、複数列ツリービューでそれを使用しようとしている場合には、それを構築するための方法ではありません。

alt text http://www.digitaltools.com/images/GVT.jpg

詳しいことはhere.

+0

最初のクエリに余分な列を追加する必要があります。したがって、すべてが同じ列数を持ち、並べ替えが役に立ちます –

+0

Ok、固定と追加。 – JBrooks

+0

私はテストテーブルとデータを使ってそれを実行すると、各 "セット"の最初と最後の行しか取得しません –

3

おそらくこれを見つけることができます最も効率的なクエリはありませんが、それはコードの最も簡単な方法です:

declare @YourTable table (CategoryId int primary key, ParentCategoryId int , CategoryName varchar(50)) 

INSERT INTO @YourTable VALUES (1, null, 'SomeRoot') 
INSERT INTO @YourTable VALUES (2, 1, 'SomeChild') 
INSERT INTO @YourTable VALUES (3, 2, 'SomeGrandchild') 
INSERT INTO @YourTable VALUES (4, 3, 'SomeGreatGrandchild') 

INSERT INTO @YourTable VALUES (10, null, 'X_SomeRoot') 
INSERT INTO @YourTable VALUES (20, 10, 'X_SomeChild') 
INSERT INTO @YourTable VALUES (30, 20, 'X_SomeGrandchild') 


Select 
    c1.CategoryId, c1.CategoryName, c2.CategoryName, c3.CategoryName, c4.CategoryName 
    From @YourTable   c1 
     INNER JOIN @YourTable c2 On c1.CategoryId = c2.ParentCategoryId 
     INNER JOIN @YourTable c3 On c2.CategoryId = c3.ParentCategoryId 
     INNER JOIN @YourTable c4 On c3.CategoryId = c4.ParentCategoryId 
    WHERE c1.ParentCategoryId IS NULL 
UNION 
Select 
    c1.CategoryId, c1.CategoryName, c2.CategoryName, c3.CategoryName, NULL 
    From @YourTable   c1 
     INNER JOIN @YourTable c2 On c1.CategoryId = c2.ParentCategoryId 
     INNER JOIN @YourTable c3 On c2.CategoryId = c3.ParentCategoryId 
    WHERE c1.ParentCategoryId IS NULL 
UNION 
Select 
    c1.CategoryId, c1.CategoryName, c2.CategoryName, NULL, NULL 
    From @YourTable   c1 
     INNER JOIN @YourTable c2 On c1.CategoryId = c2.ParentCategoryId 
    WHERE c1.ParentCategoryId IS NULL 
UNION 
Select 
    c1.CategoryId, c1.CategoryName, NULL, NULL, NULL 
    From @YourTable   c1 
    WHERE c1.ParentCategoryId IS NULL 
ORDER BY 2,3,4,5 

OUTPUT:

SortB CategoryId CategoryName CategoryName CategoryName  CategoryName 
----- ----------- ------------ ------------- ----------------- -------------------- 
1  1   SomeRoot  NULL   NULL    NULL 
2  1   SomeRoot  SomeChild  NULL    NULL 
3  1   SomeRoot  SomeChild  SomeGrandchild NULL 
4  1   SomeRoot  SomeChild  SomeGrandchild SomeGreatGrandchild 
1  10   X_SomeRoot NULL   NULL    NULL 
2  10   X_SomeRoot X_SomeChild NULL    NULL 
3  10   X_SomeRoot X_SomeChild X_SomeGrandchild NULL 

(7 row(s) affected) 
+0

@tableの挿入に感謝します。+1 – jcollum

関連する問題