2009-09-04 81 views
4

我有以下分層表:什麼是最簡單或最簡單的方法將這個heirarchical表格變成一張平坦的表格?

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

(注意,這樣的數據不包括除第4級的較早節點上的葉,但這是可能的)。如果相關的話,數據永遠不會比第4級更深。我想變換/它旋轉到這個固定的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 

我已經做了左外連接的類別表4倍,並建立了一個巨大的case語句用於檢測水平,使用的ID字段,但不包括空行....任何想法?幫幫我!

+1

您需要告訴我們數據是否始終有 jcollum 2009-09-04 20:10:46

+1

@jcollum更新問:如果相關,數據將永遠不會比第4級更深。 – TheSoftwareJedi 2009-09-04 20:13:24

+1

如果它具有未知級別的遞歸,則要使用CTE。對於已知和小的遞歸級別,我聽說CTE有太多的開銷,所以子查詢更好。 – jcollum 2009-09-04 20:32:11

回答

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

我原來是這樣的 - 但是有一個「where C.parentcategoryid爲null」來保持它離開根。但是,在上面的例子中只會返回1個結果。另外,Id將是根的 – TheSoftwareJedi 2009-09-04 20:12:10

+0

嘗試沒有where子句?導致where子句WOULD將其限制爲唯一的一個根記錄(這是唯一一個具有null parentCatId的記錄) – 2009-09-04 20:14:21

+0

我寫它的方式應該返回Category表中的每一行,因爲沒有where子句,並且聯接是所有外部連接.... – 2009-09-04 20:15:02

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 

但是,這不是構建它,如果你打算用多列的TreeView,看起來像這樣的使用方式:

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

更可以發現here.

+0

您需要爲第一個查詢添加額外的列,因此所有列都具有相同數量的列,並且排序會幫助 – 2009-09-04 20:49:03

+0

好,已修復並添加。 – JBrooks 2009-09-04 20:54:47

+0

當我運行它使用我的測試表和數據我只獲得每個「集」的第一個和最後一個行 – 2009-09-04 21:00:02

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 2009-09-04 21:27:01

相關問題