我有一个以下分层格式的表 - 输入示例1
Dim_Name |Dim_Parent
G. Manager |#root
Assistant |G. Manager
Manager |G.Manager
Sr Associate|Manager
Associate | Sr Associate
我希望将其转换为平面(“分支”视图)表 - 输出示例1
LVL3 |LVL2 |LVL1 |LVL0
G. Manager|Manager |Sr Associate|Associate
G. Manager|Assistant |Assistant |Assistant
我的要求是拥有一个可以处理未知层次结构的解决方案。例如,对于以下输入: - 输入示例2
Dim_Name |Dim_Parent
G. Manager |#root
Assistant |G. Manager
Manager |G.Manager
我的输出应该是 - 输出示例2
LVL1 |LVL0
G. Manager|Manager
G. Manager|Assistant
任何建议都会有所帮助。
答案 0 :(得分:0)
如果要多次运行,请取消注释drop table语句。同时调整输入,无论初始数据集中的内容是什么,它仍然可以正常工作
--drop table ##final
--drop table #temp
create table #temp
(rowid int identity, Dim_Name varchar(max), Dim_Parent varchar(max))
insert #temp
values
('G. Manager', '#root'),
('Assistant' , 'G. Manager') ,
('Manager' , 'G. Manager'),
('Sr Associate', 'Manager'),
('Mid Associate', 'Manager'),
('Jr Associate', 'Manager'),
('Rookie' , 'Jr Associate'),
('Newbie' , 'Jr Associate'),
('Associate' , 'Sr Associate'),
('Intern' , 'Associate')
--drop table ##holding
create table ##holding (rowid int, value1 varchar(max), value2 varchar(max))
declare @inneriterator int = 1
declare @iterator int = 1
declare @maxrowid int = (select max(rowid) from #temp)
declare @dim_parent varchar(max)
while @iterator<= @maxrowid
begin
select @dim_parent=dim_name
from #temp
where rowid=@iterator
while @inneriterator<= @maxrowid
begin
insert ##holding
select @iterator, @dim_parent, dim_name
from #temp where dim_parent=@dim_parent
set @inneriterator=@inneriterator+1
end
set @inneriterator=1
set @iterator=@iterator+1
end
select distinct rowid aa, 'left join ##holding b' a, 'on a.value2=b' b, '.value1'c
into #a from ##holding
where
value2 in (select value1 from ##holding)
select cast(row_number() over(order by aa) as varchar(max)) rownum,* into #b from #a
create table #c (rowid int identity, alias varchar(max), a varchar(max), b varchar(max), c varchar(max))
insert #c
select null,
a+cast(rownum as varchar(max))a, null b,c
from #b
update #c set alias='b'+cast(rowid as varchar(max))
select * , lag(alias, 1,'a') over(order by rowid) previousalias into #d
from #c
update #d set b='on '+previousalias+'.value2='+alias
--select * from #d
select @maxrowid=max(rowid) from #d
declare @string varchar(max)= ''
set @iterator=1
while @iterator<=@maxrowid
begin
select @string=case when @iterator=@maxrowid
then @string+alias+'.value2 as [Level '+ cast(rowid+2 as varchar(max))+'] '
else @string+alias+'.value2 as [Level '+ cast(rowid+2 as varchar(max))+'], ' end
from #d
where rowid=@iterator
set @iterator=@iterator+1
end
set @string=
case when exists(select 1 from #d)
then 'select distinct a.value1 [Level 1], a.value2 [Level 2], '+@string+ 'into ##final from ##holding a '
else 'select distinct a.value1 [Level 1], a.value2 [Level 2] '+@string+ 'into ##final from ##holding a '
end
set @iterator=1
while @iterator<=@maxrowid
begin
set @string=@string+(select a+' '+b+' '+c+' '
from #d where rowid=@iterator)
set @iterator=@iterator+1
end
--select @string
exec(''+@string+' where a.rowid=1')
create table #columns (rowid int identity, column_name varchar(max))
insert #columns
select distinct column_name from tempdb.INFORMATION_SCHEMA.COLUMNS where table_name='##final'
declare @column_name varchar(max)
set @iterator=1
select @maxrowid=max(rowid) from #columns
while @iterator<=@maxrowid
begin
select @column_name=column_name from #columns where rowid=@iterator
exec('if not exists (select 1 from ##final where ['+@column_name+'] is not null)
begin
alter table ##final
drop column ['+@column_name+'] end')
set @iterator=@iterator+1
end
set @iterator =1
declare @iterator2 int
declare @fieldname varchar(max)
declare @lastfieldname varchar(max)
while @iterator<=(select max(rowid) from #columns)
begin
select @fieldname=column_name from #columns
where rowid=@iterator
set @iterator2=@iterator-1
set @lastfieldname='Level '+cast(@iterator2 as varchar(max))
--select @lastfieldname
if @fieldname in (select column_name from tempdb.INFORMATION_SCHEMA.COLUMNS where table_name='##final')
and @lastfieldname in (select column_name from tempdb.INFORMATION_SCHEMA.COLUMNS where table_name='##final')
exec('update ##final set ['+@fieldname+']= case when ['+@fieldname+'] is null then
[Level '+@iterator2+']
else ['+@fieldname+'] end ')
set @iterator=@iterator+1
end
select * from ##final
--drop table #columns
--drop table #a
--drop table #b
--drop table #c
--drop table #d