sql With As 递归实现树形结构数据初始化

今天遇到一个问题记录下,我们需要导入其他系统的树形结构数据,但是我们这边的层级是要以 父级.子级.子级 这样的Code 才能实现,而对方给到的数据却是以当前编码和父级编码这样的数据给到我们,所以只能对编码做点改造,话不多说,直接上图,下面为待整理的数据

--表结构和数据
CREATE TABLE [dbo].[s_TreeDemo](
	[CODE] [varchar](255) NULL,
	[DISPLAYORDER] [varchar](255) NULL,
	[PARENTID] [char](12) NULL,
	[NAME] [varchar](255) NULL
) ON [PRIMARY]
GO
INSERT [dbo].[s_TreeDemo] ([CODE], [DISPLAYORDER], [PARENTID], [NAME]) VALUES (N'P0000', N'000000021348', N'0           ', N'教育')
INSERT [dbo].[s_TreeDemo] ([CODE], [DISPLAYORDER], [PARENTID], [NAME]) VALUES (N'P8300', N'000000021349', N'000000021348', N'教育')
INSERT [dbo].[s_TreeDemo] ([CODE], [DISPLAYORDER], [PARENTID], [NAME]) VALUES (N'P8310', N'000000021350', N'000000021349', N'学前教育')
INSERT [dbo].[s_TreeDemo] ([CODE], [DISPLAYORDER], [PARENTID], [NAME]) VALUES (N'P8320', N'000000021351', N'000000021349', N'初等教育')
INSERT [dbo].[s_TreeDemo] ([CODE], [DISPLAYORDER], [PARENTID], [NAME]) VALUES (N'P8321', N'000000021352', N'000000021351', N'普通小学教育')
INSERT [dbo].[s_TreeDemo] ([CODE], [DISPLAYORDER], [PARENTID], [NAME]) VALUES (N'P8322', N'000000021353', N'000000021351', N'成人小学教育')
INSERT [dbo].[s_TreeDemo] ([CODE], [DISPLAYORDER], [PARENTID], [NAME]) VALUES (N'P8330', N'000000021354', N'000000021349', N'中等教育')
INSERT [dbo].[s_TreeDemo] ([CODE], [DISPLAYORDER], [PARENTID], [NAME]) VALUES (N'P8331', N'000000021355', N'000000021354', N'普通初中教育')
INSERT [dbo].[s_TreeDemo] ([CODE], [DISPLAYORDER], [PARENTID], [NAME]) VALUES (N'P8332', N'000000021356', N'000000021354', N'职业初中教育')
INSERT [dbo].[s_TreeDemo] ([CODE], [DISPLAYORDER], [PARENTID], [NAME]) VALUES (N'P8333', N'000000021357', N'000000021354', N'成人初中教育')
INSERT [dbo].[s_TreeDemo] ([CODE], [DISPLAYORDER], [PARENTID], [NAME]) VALUES (N'P8334', N'000000021358', N'000000021354', N'普通高中教育')
INSERT [dbo].[s_TreeDemo] ([CODE], [DISPLAYORDER], [PARENTID], [NAME]) VALUES (N'P8335', N'000000021359', N'000000021354', N'成人高中教育')
INSERT [dbo].[s_TreeDemo] ([CODE], [DISPLAYORDER], [PARENTID], [NAME]) VALUES (N'P8336', N'000000021360', N'000000021354', N'中等职业学校教育')
INSERT [dbo].[s_TreeDemo] ([CODE], [DISPLAYORDER], [PARENTID], [NAME]) VALUES (N'P8340', N'000000021361', N'000000021349', N'高等教育')
INSERT [dbo].[s_TreeDemo] ([CODE], [DISPLAYORDER], [PARENTID], [NAME]) VALUES (N'P8341', N'000000021362', N'000000021361', N'普通高等教育')
INSERT [dbo].[s_TreeDemo] ([CODE], [DISPLAYORDER], [PARENTID], [NAME]) VALUES (N'P8342', N'000000021363', N'000000021361', N'成人高等教育')
INSERT [dbo].[s_TreeDemo] ([CODE], [DISPLAYORDER], [PARENTID], [NAME]) VALUES (N'P8350', N'000000021364', N'000000021349', N'特殊教育')
INSERT [dbo].[s_TreeDemo] ([CODE], [DISPLAYORDER], [PARENTID], [NAME]) VALUES (N'P8390', N'000000021365', N'000000021349', N'技能培训、教育辅助及其他教育')
INSERT [dbo].[s_TreeDemo] ([CODE], [DISPLAYORDER], [PARENTID], [NAME]) VALUES (N'P8391', N'000000021366', N'000000021365', N'职业技能培训')
INSERT [dbo].[s_TreeDemo] ([CODE], [DISPLAYORDER], [PARENTID], [NAME]) VALUES (N'P8392', N'000000021367', N'000000021365', N'体校及体育培训')
INSERT [dbo].[s_TreeDemo] ([CODE], [DISPLAYORDER], [PARENTID], [NAME]) VALUES (N'P8393', N'000000021368', N'000000021365', N'文化艺术培训')
INSERT [dbo].[s_TreeDemo] ([CODE], [DISPLAYORDER], [PARENTID], [NAME]) VALUES (N'P8394', N'000000021369', N'000000021365', N'教育辅助服务')
INSERT [dbo].[s_TreeDemo] ([CODE], [DISPLAYORDER], [PARENTID], [NAME]) VALUES (N'P8399', N'000000021370', N'000000021365', N'其他未列明教育')

数据插入后待处理的显示效果

分析:只要是树形结构的一般都会有这两个列,一个是当前节点Code 一个是父级节点Code,我们只需要递归去刷一下Code和名称就可以实现,代码如下。

WITH child (CODE, NAME, DISPLAYORDER, PARENTID, level, newCode, newName, parentCode, IfEnd)
	AS (
		SELECT
				CODE,
				NAME,
				DISPLAYORDER,
				PARENTID,
				1 AS level,
				CONVERT (VARCHAR(100), CODE) AS newCode,
				CONVERT (VARCHAR(300), NAME) AS newName,
				CODE AS parentCode,
				0 AS IfEnd
		FROM	s_TreeDemo
		WHERE DISPLAYORDER = '000000021348' --最顶级编码
		UNION ALL
		SELECT
				a.CODE,
				a.NAME,
				a.DISPLAYORDER,
				a.PARENTID,
				b.level + 1,
				CONVERT (VARCHAR(100), b.newCode + '.' + a.CODE) AS newCode,
				CONVERT (VARCHAR(300), b.newName + '-' + a.NAME) AS newName,
				b.CODE AS parentCode,
				IfEnd = (CASE
								WHEN	EXISTS
										(	SELECT
															1
												FROM		dbo.s_TreeDemo
												WHERE		PARENTID = a.DISPLAYORDER) THEN
									0
								ELSE 1
							END)
		FROM	dbo.s_TreeDemo a
				INNER JOIN child b ON a.PARENTID = b.DISPLAYORDER
		)
SELECT
			*
FROM		child
ORDER BY child.CODE;

结果
在这里插入图片描述
查询当前所有父级节点

SELECT
		*
FROM	s_TreeDemo A
WHERE NOT EXISTS
	(	SELECT
				*
		FROM	s_TreeDemo B
		WHERE A.PARENTID = B.DISPLAYORDER);

查询当前所有末级节点

SELECT
		*
FROM	s_TreeDemo A
WHERE NOT EXISTS
	(	SELECT
				*
		FROM	s_TreeDemo B
		WHERE A.DISPLAYORDER = B.PARENTID);
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用递归解决树形结构数据循环调用问题的关键是要踪已经访问过的节点,以免进入无限循环。下是一个示例,演示了如何使用递归解决树形结构数据循环调用问题: ```javascript // 树节点类 class TreeNode { constructor(value) { this.value = value; this.children = []; } addChild(childNode) { this.children.push(childNode); } } // 递归遍历树 function traverseTree(node, visitedNodes = new Set()) { // 如果节点已经被访问过,则直接返回 if (visitedNodes.has(node)) { return; } // 访问当前节点 console.log(node.value); visitedNodes.add(node); // 遍历子节点 for (const child of node.children) { traverseTree(child, visitedNodes); } } // 创建树形结构数据 const root = new TreeNode('A'); const nodeB = new TreeNode('B'); const nodeC = new TreeNode('C'); const nodeD = new TreeNode('D'); const nodeE = new TreeNode('E'); root.addChild(nodeB); root.addChild(nodeC); nodeB.addChild(nodeD); nodeD.addChild(nodeE); // 循环调用测试 nodeE.addChild(root); // 在 E 节点中添加对根节点的引用 // 使用递归遍历树 const visitedNodes = new Set(); traverseTree(root, visitedNodes); ``` 在这个示例中,我们定义了一个 `TreeNode` 类表示树的节点,每个节点都有一个值属性 `value` 和一个子节点数组 `children`。我们使用 `addChild` 方法添加子节点。 `traverseTree` 函数用于递归遍历树,并通过一个 `Set` 数据结构来记录已经访问过的节点,以防止无限循环。在访问节点时,我们打印节点的值,并将节点添加到已访问节点集合中。 在创建树形结构数据后,我们对节点 `E` 执行了一个循环调用测试,将根节点 `A` 作为子节点添加到了 `E` 节点。在使用递归遍历树时,我们传入一个空的已访问节点集合,并在遍历过程中传递该集合,确保只访问未被访问过的节点,避免了无限循环。 请注意,以上示例仅提供了一个基本的使用递归解决树形结构数据循环调用问题的思路。在实际应用中,可能需要根据具体情况进行适当的调整和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值