因此,因为我为我的假表/数据使用了两个 CTE,所以使用 Recursive CTE 如果它不是 WITH 之后的第一个项目,它似乎会出错,我将它插入到子 CTE 中。一旦建立了关系,我们就可以再次双重连接维度以获取名称。
WITH dimension_territory(territory_key, territory_name) AS (
SELECT * FROM VALUES
(1, 'WorldWide'),
(2, 'Western Hemisphere'),
(3, 'North America'),
(4, 'Canada')
), territory_member_list(parent_territory_key, child_territory_key) AS (
SELECT * FROM VALUES
(1, 2),
(2, 3),
(3, 4)
), h_cte AS (
WITH RECURSIVE hierarchy(p_key, c_key, is_root, edge_distance) AS (
-- Anchor Clause
SELECT territory_key
,territory_key
,territory_key = 1
,0
FROM dimension_territory
--WHERE parent_territory_key = 1
UNION ALL
-- Recursive Clause
SELECT h.p_key
,ml.child_territory_key
,false
,edge_distance + 1
FROM territory_member_list AS ml
JOIN hierarchy AS h
ON ml.parent_territory_key = h.c_key --OR ml.child_territory_key =
)
SELECT * FROM hierarchy
)
SELECT d_p.territory_key as ancestor_territory_key
,d_p.territory_name as ancestor_territory_name
,d_c.territory_key as descendant_territory_key
,d_c.territory_name as descendant_territory_name
,h.is_root
,h.edge_distance
FROM h_cte as h
JOIN dimension_territory AS d_p
ON h.p_key = d_p.territory_key
JOIN dimension_territory AS d_c
ON h.c_key = d_c.territory_key
ORDER BY 1,2;
给予:
ANCESTOR_TERRITORY_KEY ANCESTOR_TERRITORY_NAME DESCENDANT_TERRITORY_KEY DESCENDANT_TERRITORY_NAME IS_ROOT EDGE_DISTANCE
1 WorldWide 1 WorldWide TRUE 0
1 WorldWide 2 Western Hemisphere FALSE 1
1 WorldWide 3 North America FALSE 2
1 WorldWide 4 Canada FALSE 3
2 Western Hemisphere 2 Western Hemisphere FALSE 0
2 Western Hemisphere 3 North America FALSE 1
2 Western Hemisphere 4 Canada FALSE 2
3 North America 3 North America FALSE 0
3 North America 4 Canada FALSE 1
4 Canada 4 Canada FALSE 0
因为您想要的输出是想要每个节点的子树,所以我在 Anchor 子句中从 dimension_territory 中选择所有节点,这允许通过假设 1 是根来设置 is_root,并将每个距离设置为 0 . 从那里递归子句将递归数据与边缘列表连接起来,以构建子节点集。
所以要摆脱“数据”CTE,这看起来像:
WITH RECURSIVE hierarchy(p_key, c_key, is_root, edge_distance) AS (
-- Anchor Clause
SELECT territory_key
,territory_key
,territory_key = 1
,0
FROM dimension_territory
UNION ALL
-- Recursive Clause
SELECT h.p_key
,ml.child_territory_key
,false
,edge_distance + 1
FROM territory_member_list AS ml
JOIN hierarchy AS h
ON ml.parent_territory_key = h.c_key --OR ml.child_territory_key =
)
SELECT d_p.territory_key as ancestor_territory_key
,d_p.territory_name as ancestor_territory_name
,d_c.territory_key as descendant_territory_key
,d_c.territory_name as descendant_territory_name
,h.is_root
,h.edge_distance
FROM hierarchy as h
JOIN dimension_territory AS d_p
ON h.p_key = d_p.territory_key
JOIN dimension_territory AS d_c
ON h.c_key = d_c.territory_key
ORDER BY 1,2;