假设我有这样的表:
id parent_id name
11 NULL Company
33 11 Department 1
44 33 Department 2
我想将其转换为:
id parent_id name Level1 Level2 Level3
11 NULL Company NULL NULL NULL
22 11 Company Department 1 NULL NULL
33 22 Company Department 1 Department 2 NULL
我能够创建一个CTE,并在Levels列中显示层次结构中的值,但我不知道如何为所显示的部门创建新列。
with myCTE as (
select c.id, c."name", c.parent_id, 1 as Level
from table1 c
where c.parent_id IS NULL
UNION ALL
Select c1.id, c1."name", c1.parent_id, Level +1
from table1 c1
inner join myCTE on c1.parent_id = myCTE.id
where c1.parent_id IS NOT NULL
)
select * from myCTE
表示:
id parent_id name level
1 11 NULL Company 1
2 22 11 Department 2 2
3 33 22 Department 3 3
答案 0 :(得分:2)
(几乎)完全通用的方法:
DECLARE @tbl TABLE(id INT,parent_id INT,name VARCHAR(100));
INSERT INTO @tbl VALUES
(11,NULL,'Company')
,(33,11,'Department 1')
,(44,33,'Department 2a')
,(55,33,'Department 2b')
,(66,44,'SubDep 2a');
- 递归CTE将在逐行级别构建XML片段
- SELECT将使用XML方法.nodes()
和ROW_NUMBER
生成PIVOT
WITH recCTE AS
(
SELECT id, parent_id,name,(SELECT name AS [*] FOR XML PATH('')) AS NameConcat
FROM @tbl WHERE parent_id IS NULL
UNION ALL
SELECT t.id,t.parent_id,t.name,recCTE.NameConcat + '</lvl><lvl>' + (SELECT t.name AS [*] FOR XML PATH(''))
FROM @tbl AS t
INNER JOIN recCTE ON recCTE.id=t.parent_id
)
SELECT p.*
FROM
(
SELECT id
,parent_id
,name
,'Level' + REPLACE(STR(ROW_NUMBER() OVER(PARTITION BY id ORDER BY (SELECT NULL)),2),' ','0') AS HierarchyRank
,lvl.value(N'(./text())[1]','nvarchar(max)') AS HierarchyName
FROM recCTE
CROSS APPLY (SELECT CAST('<lvl>' + NameConcat + '</lvl>' AS XML) AS PreLevels ) AS Casted
CROSS APPLY Casted.PreLevels.nodes(N'/lvl') AS A(lvl)
) AS tbl
PIVOT
(
MAX(HierarchyName) FOR HierarchyRank IN(Level01,Level02,Level03,Level04,Level05,Level06,Level07,Level08,Level09)
) AS p;
结果
+----+-----------+----------------+---------+----------------+---------------+-----------+---------+
| id | parent_id | name | Level01 | Level02 | Level03 | Level04 | Level05 |
+----+-----------+----------------+---------+----------------+---------------+-----------+---------+
| 11 | NULL | Company | Company | NULL | NULL | NULL | NULL |
+----+-----------+----------------+---------+----------------+---------------+-----------+---------+
| 33 | 11 | Department 1 | Company | Department 1 | NULL | NULL | NULL |
+----+-----------+----------------+---------+----------------+---------------+-----------+---------+
| 44 | 33 | Department 2a | Company | Department 1 | Department 2a | NULL | NULL |
+----+-----------+----------------+---------+----------------+---------------+-----------+---------+
| 55 | 33 | Department 2b | Company | Department 1 | Department 2b | NULL | NULL |
+----+-----------+----------------+---------+----------------+---------------+-----------+---------+
| 66 | 44 | SubDep 2a | Company | Department 1 | Department 2a | SubDep 2a | NULL |
+----+-----------+----------------+---------+----------------+---------------+-----------+---------+
如果您需要更多关卡,唯一需要在PIVOT
部分添加更多列名...
答案 1 :(得分:0)
您可以计算每个级别的行,并将它们联合起来:
with MyCTE as (
select id, parent_id, name, null as level1, null as level2, null as level3
from table1 as root
where root.parent_id is null
union
select level1.id, level1.parent_id, root.name, level1.name as level1, null as level2, null as level3
from table1 as level1
inner join table1 as root on root.id = level1.parent_id
where root.parent_id is null
union
select level2.id, level2.parent_id, root.name, level1.name as level1, level2.name as level2, null as level3
from table1 as level2
inner join table1 as level1 on level1.id = level2.parent_id
inner join table1 as root on root.id = level1.parent_id
where root.parent_id is null
union
select level3.id, level3.parent_id, root.name, level1.name as level1, level2.name as level2, level3.name as level3
from table1 as level3
inner join table1 as level2 on level2.id = level3.parent_id
inner join table1 as level1 on level1.id = level2.parent_id
inner join table1 as root on root.id = level1.parent_id
where root.parent_id is null
)
select * from MyCTE
如果您需要更多级别,则需要添加更多带有其他联接的选择