2012-06-27 4 views
3

У меня есть таблица вроде этого:PIVOT иерархических данных

 
Id Name    parentId 
-------------------------------- 
5 Rollers    2 
2 Paint and Brushes 1 
1 Decorating   NULL 

Использование PIVOT или любой другой запрос, я могу получить выход так:

 
cat1id cat1name  cat2id cat2name    cat3id cat3Name 
------------------------------------------------------------------------ 
1  Decorating 2   Paint and Brushes 5   Rollers 
+0

см этот [] (http://stackoverflow.com/questions/11070158/sql-server-column-to-row/11070643#11070643) вопрос, схожие с вашими , – 03Usr

ответ

5

Вы можете использовать PIVOT, UNPIVOT и рекурсивный запрос для выполнения этого.

Статическая версия, где вы жестко закодировать значения в трансформированном:

;with hd (id, name, parentid, category) 
as 
(
    select id, name, parentid, 1 as category 
    from yourtable 
    where parentid is null 
    union all 
    select t1.id, t1.name, t1.parentid, hd.category +1 
    from yourtable t1 
    inner join hd 
    on t1.parentid = hd.id 
), 
unpiv as 
(
    select value, 'cat_'+cast(category as varchar(5))+'_'+ col col_name 
    from 
    (
    select cast(id as varchar(17)) id, name, parentid, category 
    from hd 
) src 
    unpivot 
    (
    value for col in (id, name) 
) un 
) 
select [cat_1_id], [cat_1_name], 
        [cat_2_id], [cat_2_name], 
        [cat_3_id], [cat_3_name] 
from unpiv 
pivot 
(
    max(value) 
    for col_name in ([cat_1_id], [cat_1_name], 
        [cat_2_id], [cat_2_name], 
        [cat_3_id], [cat_3_name]) 
) piv 

См SQL Fiddle with Demo

динамической версии значения генерируются во время выполнения:

;with hd (id, name, parentid, category) 
as 
(
    select id, name, parentid, 1 as category 
    from yourtable 
    where parentid is null 
    union all 
    select t1.id, t1.name, t1.parentid, hd.category +1 
    from yourtable t1 
    inner join hd 
    on t1.parentid = hd.id 
) 
select category categoryNumber 
into #temp 
from hd 

DECLARE @cols AS NVARCHAR(MAX), 
    @query AS NVARCHAR(MAX) 

select @cols = STUFF((SELECT distinct ',' + quotename('cat_'+cast(CATEGORYNUMBER as varchar(10))+'_'+col) 
        from #temp 
        cross apply (select 'id' col 
           union all 
           select 'name' col) src 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = ';with hd (id, name, parentid, category) 
       as 
       (
       select id, name, parentid, 1 as category 
       from yourtable 
       where parentid is null 
       union all 
       select t1.id, t1.name, t1.parentid, hd.category +1 
       from yourtable t1 
       inner join hd 
        on t1.parentid = hd.id 
      ), 
       unpiv as 
       (
       select value, ''cat_''+cast(category as varchar(5))+''_''+ col col_name 
       from 
       (
        select cast(id as varchar(17)) id, name, parentid, category     
        from hd 
       ) src 
       unpivot 
       (
        value for col in (id, name) 
       ) un 
      ) 
       select '[email protected]+' 
       from unpiv 
       pivot 
       (
       max(value) 
       for col_name in ('[email protected]+') 
       ) piv' 

execute(@query) 

drop table #temp 

См. SQL Fiddle with Demo

The Re зультатов одинаковы для обоих:

| CAT_1_ID | CAT_1_NAME | CAT_2_ID |  CAT_2_NAME | CAT_3_ID | CAT_3_NAME | 
-------------------------------------------------------------------------------- 
|  1 | Decorating |  2 | Paint and Brushes |  5 | Rollers | 
Смежные вопросы