我有一个包含以下数据的表dbo.Hierarchy:
Level1 Level2 Level3 Level4 Level5 Level6 Level7 Level8 Level9 Level10
-----------------------------------------------------------------------
a b c d e f g h i j
k l m n o
总共有10个级别,任何项目都可以具有任何级别的层次结构。在上面的数据中,a是b的父级,b是c的父级,依此类推。 j和o是各自层次结构中的最后一个级别。如何以下列格式获得输出:
Name ParentName LevelID
-------------------------------
a NULL 1
b a 2
j i 10
k NULL 1
l k 2
o n 5
答案 0 :(得分:0)
试试这个:
;with base as
(select *, row_number() over (order by level1) rn from tbl),
src as
(
select
valname as name,
cast(substring(colname,6,len(colname)) as int) as level,
rn from
(select * from base) s
unpivot
(
valname
for colname in ([level1],[level2],[level3],[level4],[level5],[level6],[level7], [level8],[level9],[level10])
) u
),
cte as
(select * from src
where level = 1
union all
select s.* from src s
inner join cte c on s.level = c.level + 1 and s.rn = c.rn)
select distinct s.name, t.name parentname, s.level levelid from
cte s
left join cte t on s.rn = t.rn and s.level = t.level + 1
故障:
UNPIVOT
,我们会将数据集减少到3列 - name
,level
和行号rn
。LEFT JOIN
cte 自身,条件是连接两侧的行号相同,即值属于基表中的相同记录,并且右侧的值是左侧值的直接祖先(父级)。如果要为表选择规范化结构,可以避免上面的大量代码。我会建议这样的事情:
CREATE TABLE tbl
(ID int, --Keep track of values that are related to each other
Name varchar(100), --Name
Level int --The level for a particular value
)
使用这个提议的结构,您只需要递归CTE(来自上面代码的cte
)和左连接来获取父子数据。这种方法的优点在于您可以将其扩展到您喜欢的任意数量的级别,而无需对级别编号进行硬编码。
答案 1 :(得分:0)
像(未经测试的)
with t(L1,L2,L3,L4,L5,L6,L7,L8,L9,L10) as (
values ('a','b','c','d','e','f','g','h','i','j')
, ('k','l','m','n','o',null,null,null,null,null)
)
select x.*
from t
cross apply (
values (L1,null,1),(L2,L1,2),(L3,L2,3),(L4,L3,4),(L5,L4,5)
, (L6,L5,6),(L7,L6,7),(L8,L7,8),(L9,L8,9),(L10,L9,10)) x (name, parentname, levelid)
where name is not null