如何在SQL Server 2008中展平类别层次结构?

时间:2011-11-30 00:37:08

标签: sql-server-2008

我有一个包含类别层次结构的表。它可以有任意数量的类别级别。

我需要以简单的字符串格式显示这些类别,即:

>>parent>>child1>>subchild>>...

这是数据样本:

Id  Parent  Name
1   NULL    Categories
4   NULL    Instrument
55  NULL    Genre
65  NULL    Geographical Place 
8   1   CLASSICAL
47  1   SOLO INSTRUMENTS
10694   1   STYLES
4521    4   Piano
1137    8   SOLO INSTRUMENTS
1140    8   WALTZES
841 47  PIANO
93328   55  CLASSICAL
93331   55  BLUES
93334   55  CLUB / ELECTRONICA
93339   55  CONTEMPORARY FOLK
93344   55  CHILDREN
94892   65  EUROPE
4180    10694   CLASSICAL - SOLO PIANO
94893   94892   Western & Southern  Europe
94900   94893   France

2 个答案:

答案 0 :(得分:2)

也许有人有更好的方法来完成最后一部分(摆脱中间字符串),但这就是你在那里没有硬编码任何连接:

declare @Categories table
(
    categoryID int,
    categoryParentID int,
    categoryDesc nvarchar(100)
)
insert into @Categories values
(1,NULL,'Categories'),
(4,NULL,'Instrument'),
(55,NULL,'Genre'),
(65,NULL,'Geographical Place '),
(8,1,'CLASSICAL'),
(47,1,'SOLO INSTRUMENTS'),
(10694,1,'STYLES'),
(4521,4,'Piano'),
(1137,8,'SOLO INSTRUMENTS'),
(1140,8,'WALTZES'),
(841,47,'PIANO'),
(93328,55,'CLASSICAL'),
(93331,55,'BLUES'),
(93334,55,'CLUB / ELECTRONICA'),
(93339,55,  'CONTEMPORARY FOLK'),
(93344,55,'CHILDREN'),
(94892,65,'EUROPE'),
(4180,10694,'CLASSICAL - SOLO PIANO'),
(94893,94892,'Western & Southern  Europe'),
(94900,94893,'France')

;with CategoryCTE (categoryID, categoryString) as
(
    select categoryID, cast(categoryDesc as nvarchar(max)) as categoryString
    from @Categories 
    where categoryParentID is null

    union all

    select rsCat.categoryID, cast(CategoryCTE.categoryString + N'>>' + rsCat.categoryDesc as nvarchar(max))
    from @Categories rsCat
    inner join CategoryCTE on rsCat.categoryParentID = CategoryCTE.categoryID
)
select categoryString 
from CategoryCTE o
where not exists
(
    --eliminate intermediate strings
    select i.categoryString
    from CategoryCTE i
    where LEN(i.categoryString) != LEN(o.categoryString)
    and CHARINDEX(o.categoryString, i.categoryString) > 0
)

Working example.

答案 1 :(得分:1)

您的数据看起来像4个类别,所以您可以尝试这样的事情:

    SELECT parent.Name, child.Name, subchild.Name, subchild2.Name
    FROM categories parent
    LEFT JOIN categories child ON parent.Id = child.Parent
    LEFT JOIN categories subchild ON child.Id = subchild.Parent
    LEFT JOIN categories subchild2 ON subchild.Id = subchild2.Parent
    WHERE parent.Parent is NULL;

当然,如果您最终拥有超过4个级别的类别,则需要对其进行调整。对于不能扩展到所有4个级别的层次结构,此方法也将最终产生NULL结果。