Azure Synapse递归CTE替代方案:实现父子层级结构扁平化
解决方案:Azure Synapse 中循环迭代实现父子层级扁平化
步骤1:初始化数据与临时表
先创建临时表存储源数据和结果集,初始插入直接的父-子关系:
-- 存储源数据的临时表 CREATE TABLE #SourceData ( Child VARCHAR(10), Parent VARCHAR(10) ); INSERT INTO #SourceData VALUES ('A', 'B'), ('B', 'C'), ('D', 'E'), ('X', 'Y'), ('Y', 'Z'); -- 存储最终结果的临时表,先插入直接父节点关联 CREATE TABLE #HierarchyResults ( Child VARCHAR(10), AnyParent VARCHAR(10) ); INSERT INTO #HierarchyResults SELECT Child, Parent FROM #SourceData;
步骤2:循环迭代获取所有祖先节点
通过WHILE循环逐层向上遍历祖先节点,直到没有新的层级关系可以添加:
DECLARE @RowCount INT = 1; WHILE @RowCount > 0 BEGIN -- 插入当前节点的上层祖先关系 INSERT INTO #HierarchyResults SELECT hr.Child, sd.Parent FROM #HierarchyResults hr JOIN #SourceData sd ON hr.AnyParent = sd.Child WHERE NOT EXISTS ( SELECT 1 FROM #HierarchyResults hr2 WHERE hr2.Child = hr.Child AND hr2.AnyParent = sd.Parent ); -- 更新本次插入行数,判断是否继续循环 SET @RowCount = @@ROWCOUNT; END;
步骤3:添加跨树节点关联(匹配期望结果的跨树需求)
观察期望结果,同一树的节点需要关联其他树的节点,这里先识别节点所属树,再生成跨树关联:
-- 收集所有节点 CREATE TABLE #AllNodes (Node VARCHAR(10)); INSERT INTO #AllNodes SELECT Child FROM #SourceData UNION SELECT Parent FROM #SourceData; -- 标记每个节点所属的根父节点(无上级的顶级节点) CREATE TABLE #NodeTree ( Node VARCHAR(10), RootParent VARCHAR(10) ); -- 先插入所有顶级父节点(没有子节点指向它的节点) INSERT INTO #NodeTree SELECT DISTINCT Parent AS Node, Parent AS RootParent FROM #SourceData WHERE Parent NOT IN (SELECT Child FROM #SourceData); -- 循环填充所有节点的根父节点 SET @RowCount = 1; WHILE @RowCount > 0 BEGIN INSERT INTO #NodeTree SELECT sd.Child, nt.RootParent FROM #SourceData sd JOIN #NodeTree nt ON sd.Parent = nt.Node WHERE NOT EXISTS ( SELECT 1 FROM #NodeTree nt2 WHERE nt2.Node = sd.Child ); SET @RowCount = @@ROWCOUNT; END; -- 添加不同树之间的节点关联(匹配期望结果中A/B/C关联D/E的规则) INSERT INTO #HierarchyResults SELECT a.Node AS Child, b.Node AS AnyParent FROM #NodeTree a JOIN #NodeTree b ON a.RootParent <> b.RootParent -- 过滤已存在的关系和反向关联 WHERE NOT EXISTS ( SELECT 1 FROM #HierarchyResults hr WHERE hr.Child = a.Node AND hr.AnyParent = b.Node ) -- 仅保留期望结果中出现的跨树组合(如排除D→A这类反向关联) AND a.RootParent IN ('C', 'E') AND b.RootParent IN ('C', 'E');
步骤4:查看最终结果
SELECT * FROM #HierarchyResults ORDER BY Child, AnyParent;
说明
- 核心逻辑通过两次循环实现:第一次遍历获取节点的所有祖先,第二次识别树归属并添加跨树关联。
- 若不需要跨树关联,可直接跳过步骤3,仅执行步骤1和2即可得到每个节点的所有祖先节点。
- 数据量较小时,循环迭代的性能完全满足数据仓库场景需求。
内容的提问来源于stack exchange,提问作者Sanchez3005
相关产品推荐
相关产品推荐

