透视没有聚合的层次结构表

时间:2014-06-08 08:01:56

标签: sql sql-server

我有一个包含2列的表[部门]:

[ IdDepartment

[ IdSubDepartment

该表是一种层次结构:

IdDepartment | IdSubDepartment

1            | 2

1            | 3

2            | 4

3            | 5

如果我搜索部门 5 ,我想获得以下5 - > 3 - > 1 (我每次只需要X级 - 并不总是根)。

我编写了一个获取部门ID并返回其第3级的查询(比如我输入ID 5并返回1)。它工作得很快,很好。问题是当我为7K部门做这件事时,它会被卡住。

我想将表格转换为这样的支点:

IdDepartment0 | IdDepartment1 | IdDepartment2 ...

1               2               4

1               3               5

重要:我知道每个部门的级别。 所以,当我得到第5部门时,我知道它在第2级(IdDepartment2) 所以我可以立即查询我的新表并获得我想要的每个部门级别。

如何转换为新表?

提前谢谢 叶兰

1 个答案:

答案 0 :(得分:0)

此剪辑可以扩展为包括更深的嵌套。

它可能会被优化一些。

;WITH cteLvl AS
(
    SELECT IdDepartment, IdSubDepartment, 0 AS Lvl
    FROM Department 
    WHERE IdDepartment NOT IN (SELECT IdSubDepartment FROM Department WHERE IdSubDepartment IS NOT NULL)
    UNION ALL
    SELECT B.IdDepartment, B.IdSubDepartment, A.Lvl + 1
    FROM cteLvl A
    INNER JOIN Department B ON B.IdDepartment = A.IdSubDepartment       
)
, cteLeaf AS
(
    SELECT *, ROW_NUMBER() OVER(ORDER BY IdDepartment) AS GroupId
    FROM Department 
    WHERE IdSubDepartment IS NULL
    UNION ALL
    SELECT B.IdDepartment, B.IdSubDepartment, A.GroupId
    FROM cteLeaf A
    INNER JOIN Department B ON A.IdDepartment = B.IdSubDepartment   
)
, cteCombined AS
(
    SELECT A.IdDepartment, A.GroupId, B.Lvl FROM cteLeaf A
    INNER JOIN (SELECT DISTINCT IdDepartment, Lvl FROM cteLvl) B ON A.IdDepartment = B.IdDepartment
)

--SELECT * FROM cteCombined

SELECT GroupId, [0] AS Dep0, [1] AS Dep1, [2] AS Dep2, [3] AS Dep3, [4] AS Dep4
FROM 
(SELECT GroupId, Lvl, IdDepartment
FROM cteCombined) P
PIVOT
(
SUM(IdDepartment)
FOR Lvl IN
( [0], [1], [2], [3], [4] )
) AS V

不使用PIVOT结构的效果相同:

SELECT
GroupId,
MAX(CASE Lvl WHEN 0 THEN IdDepartment END) AS Dep0,
MAX(CASE Lvl WHEN 1 THEN IdDepartment END) AS Dep1,
MAX(CASE Lvl WHEN 2 THEN IdDepartment END) AS Dep2,
MAX(CASE Lvl WHEN 3 THEN IdDepartment END) AS Dep3
FROM cteCombined
GROUP BY GroupId