SQL递归查询行转列

在SQL环境中,将树形结构转换为分级节点表是常见的需求。本文介绍了如何通过递归查询和行转列操作来实现这一目标,同时感谢CSDN上的ch357313771和排山倒海呦提供的思路。通过构建CTE(公共表表达式)逐步形成所需结果,最终达成与预期一致的节点分级表。

由于工作环境中需要在SQL环境中实现树表到节点分级表的转换,引用链接中实例链接在此

   #Categorytree表:

IDParentIDCategoryID
101
202
313
434
527

 

#Category表:

CategoryIDCategoryNameLevelID
1企划1
2开发1
3年度计划2
4项目A3
7模块开发2

#Categorylevel表:

LevelIDCategorylevelName
1分类一
2分类二
3分类三

对于递归查询以及行转列的问题在CSDN有很多大佬答疑,但是运行出的结果确不能达到版主想要的如下效果:

 

部门树图

 从以上的逻辑结构树以及最初拥有的3张原始表,得到以下的节点分级表:

rid分类一分类二分类三
1企划NULLNULL
2开发NULLNULL
3企划年度计划NULL
4企划年度计划项目A
5开发模块开发NULL

 

 

在此感谢原回答中两位大佬 chen357313771排山倒海呦提供思路,根据两位给出的答案(虽然不能得到最终结果)修正后能够实现以上效果的代码如下:

IF OBJECT_ID('tempdb..#Categorytree','U') IS NOT NULL DROP TABLE #Categorytree
CREATE TABLE #Categorytree
(
    ID             INT
    ,ParentID     INT
    ,CategoryID     INT
)
 
INSERT INTO #Categorytree
SELECT 1, 0, 1 UNION ALL 
SELECT 2, 0, 2 UNION ALL
SELECT 3, 1, 3 UNION ALL
SELECT 4, 3, 4 UNION ALL
SELECT 5, 2, 7

IF OBJECT_ID('tempdb..#Categorytree','U') IS NOT NULL DROP TABLE #Category
CREATE TABLE #Category
(
    CategoryID        INT
    ,CategoryName    NVARCHAR(20)
    ,LevelID        INT
)
 
INSERT INTO #Category
SELECT 1, N'企划', 1 UNION ALL
SELECT 2, N'开发', 1 UNION ALL
SELECT 3, N'年度计划', 2 UNION ALL
SELECT 4, N'项目A', 3 UNION ALL
SELECT 7, N'模块开发', 2 
 
IF OBJECT_ID('tempdb..#Categorytree','U') IS NOT NULL DROP TABLE #Categorylevel
CREATE TABLE #Categorylevel
(
    LevelID                INT
    ,CategorylevelName    NVARCHAR(20)
)
 
 
INSERT INTO #Categorylevel
SELECT 1,N'分类一' UNION ALL
SELECT 2,N'分类二' UNION ALL
SELECT 3,N'分类三'
 
;WITH  CTE2
AS (
    SELECT CategoryID as ID,ID as rid
    FROM #Categorytree
    UNION ALL 
    SELECT ParentID,A.rid
    FROM CTE2 AS A
    JOIN #Categorytree AS B ON A.ID=B.CategoryID
    WHERE ParentID>0
) 
, CTE3
AS
(
SELECT A.*, C.CategorylevelName,B.CategoryName
FROM CTE2 AS A
JOIN #Category AS B ON A.ID=B.CategoryID
JOIN #Categorylevel AS C ON B.LevelID=C.LevelID
)

select rid,[分类一],[分类二],[分类三] 
from (select rid,CategorylevelName,CategoryName from CTE3) as src
pivot
(
max(CategoryName)
for CategorylevelName in([分类一],[分类二],[分类三])
) as p

 思路为,递归出所有节点父节点表CTE2,再给CTE2里面的所有父节点赋上对应的名字和所在层级到CTE3,再对CTE3表的原始id(rid)的所有父节点做层级分类得到最终结果如效果图中所展示的一致。

项目(fwE9)内实现:

IF OBJECT_ID('tempdb..#Categorytree','U') IS NOT NULL DROP TABLE #Categorytree;
IF OBJECT_ID('tempdb..#Category','U') IS NOT NULL DROP TABLE #Category;
IF OBJECT_ID('tempdb..#Categorylevel','U') IS NOT NULL DROP TABLE #Categorylevel;
create table #Categorytree
(
    ID             INT
    ,ParentID     INT
    ,CategoryID     INT
	,tempLevel    INT
)
insert into #Categorytree(ID,ParentID,CategoryID)  select id,supdepid,id from HrmDepartment

CREATE TABLE #Category
(
    CategoryID        INT
    ,CategoryName    NVARCHAR(20)
    ,LevelID        INT
)
insert into #Category select id,departmentname,0 from HrmDepartment

CREATE TABLE #Categorylevel
(
    LevelID                INT
    ,CategorylevelName    NVARCHAR(20)
)
INSERT INTO #Categorylevel
SELECT 1,N'一级部门' UNION ALL
SELECT 2,N'二级部门' UNION ALL
SELECT 3,N'三级部门' UNION ALL
SELECT 4,N'四级部门' UNION ALL
SELECT 5,N'五级部门' UNION ALL
SELECT 6,N'六级部门' UNION ALL
SELECT 7,N'七级部门' UNION ALL
SELECT 8,N'八级部门' 

--更新#Category 中的LevelID
update #Categorytree set tempLevel=1 where ParentID=0
while exists (select * from #Categorytree where tempLevel is NULL)
BEGIN
update T set T.tempLevel=P.tempLevel + 1
from #Categorytree as T inner join #Categorytree as P
on (T.ParentID=P.CategoryID) 
where P.tempLevel >= 1 and T.tempLevel is null
END
update A set A.LevelID=B.tempLevel from #Category as A inner join #Categorytree B on A.CategoryID=B.CategoryID

;WITH  CTE2
AS (
    SELECT CategoryID as ID,ID as rid
    FROM #Categorytree
    UNION ALL 
    SELECT ParentID,A.rid
    FROM CTE2 AS A
    JOIN #Categorytree AS B ON A.ID=B.CategoryID
    WHERE ParentID>0
) 
, CTE3
AS
(
SELECT A.*, C.CategorylevelName,B.CategoryName
FROM CTE2 AS A
JOIN #Category AS B ON A.ID=B.CategoryID
JOIN #Categorylevel AS C ON B.LevelID=C.LevelID
)

select rid,[一级部门],[二级部门],[三级部门],[四级部门],[五级部门],[六级部门],[七级部门],[八级部门]
from (select rid,CategorylevelName,CategoryName from CTE3) as src
pivot
(
max(CategoryName)
for CategorylevelName in([一级部门],[二级部门],[三级部门],[四级部门],[五级部门],[六级部门],[七级部门],[八级部门])
) as p

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值