如何在单独的列中显示位置结构

时间:2013-01-16 19:37:52

标签: sql sql-server sql-server-2008 tsql

我有以下Location

ID  Name       ParentID
-----------------------
1   TopLevel   NULL
2   Region 1   1
3   Fleet 1    2
4   Fleet 2    2

我最近刚刚编写了一个递归CTE,以层次结构的方式显示这个结构:

TopLevel
-Region 1
--Fleet 1
--Fleet 2

我现在需要编写一个查询来以列分层格式返回此结构:

Level1     Level2   Level3  Level4  Level5  Level6
Top Level
Top Level  Region 1 Fleet 1
Top Level  REgion 1 Fleet 2

一个位置可以达到的最高水平是9.我将如何实现这一目标?我试图使用递归CTE并在此基础上构建,但我认为这不会起作用。还有其他想法吗?

2 个答案:

答案 0 :(得分:1)

这将是一种完成输出的方法,使用硬编码的递归CTE来填充多达9级的层次结构(您需要根据实际对象名称更改表/列引用,并且您如果varchar(50)列的实际类型比此更广,则可能需要增加name

with cte as (
  select id, 1 as level,
    name as level1,
    cast(null as varchar(50)) as level2,
    cast(null as varchar(50)) as level3,
    cast(null as varchar(50)) as level4,
    cast(null as varchar(50)) as level5,
    cast(null as varchar(50)) as level6,
    cast(null as varchar(50)) as level7,
    cast(null as varchar(50)) as level8,
    cast(null as varchar(50)) as level9
  from table1 t
  where parentid is null

  union all

  select t.id, cte.level + 1 as level,
    case when level = 0 then t.name else cte.level1 end as level1,
    case when level = 1 then t.name else cte.level2 end as level2,
    case when level = 2 then t.name else cte.level3 end as level3,
    case when level = 3 then t.name else cte.level4 end as level4,
    case when level = 4 then t.name else cte.level5 end as level5,
    case when level = 5 then t.name else cte.level6 end as level6,
    case when level = 6 then t.name else cte.level7 end as level7,
    case when level = 7 then t.name else cte.level8 end as level8,
    case when level = 8 then t.name else cte.level9 end as level9
  from table1 t
  inner join cte on cte.id = t.parentid
)
select * from cte;

示例输出:

| ID | LEVEL |   LEVEL1 |   LEVEL2 |  LEVEL3 | LEVEL4 | LEVEL5 | LEVEL6 | LEVEL7 | LEVEL8 | LEVEL9 |
----------------------------------------------------------------------------------------------------
|  1 |     1 | TopLevel |   (null) |  (null) | (null) | (null) | (null) | (null) | (null) | (null) |
|  2 |     2 | TopLevel | Region 1 |  (null) | (null) | (null) | (null) | (null) | (null) | (null) |
|  3 |     3 | TopLevel | Region 1 | Fleet 1 | (null) | (null) | (null) | (null) | (null) | (null) |
|  4 |     3 | TopLevel | Region 1 | Fleet 2 | (null) | (null) | (null) | (null) | (null) | (null) |

演示:http://www.sqlfiddle.com/#!6/0bd5d/14

答案 1 :(得分:0)

我可以看到使用9个UNION语句,这样你就可以获得所需的输出,但它不会很漂亮。

这里有3个级别(你应该可以相应地添加):

SELECT Name as Level1, '' as Level2, '' as Level3
FROM Location
WHERE ParentId IS NULL
UNION
SELECT L1.Name as Level1, L2.Name as Level2, '' as Level3
FROM Location L1
JOIN Location L2 
    ON L1.Id = L2.ParentId 
    AND L1.ParentId IS NULL
UNION
SELECT L1.Name as Level1, L2.Name as Level2, L3.Name as Level3
FROM Location L1
JOIN Location L2 
    ON L1.Id = L2.ParentId 
    AND L1.ParentId IS NULL
JOIN Location L3 
    ON L2.Id = L3.ParentId 
    AND L1.ParentId IS NULL

依此类推,等等为每个后续级别的Joins添加更多表格。似乎可能有一个更好/更简单的方式,只是我能想到的唯一一个问题。

这是Fiddle