2009-09-04 57 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

相关问题