我有一个表中许多不同的层次结构集的数据,例如子父关系,我需要对所有单独的层次结构进行分组。
例如:特定层次结构的所有成员都将在一个组中。
**Input**
party related_party
1 2
1 3
3 4
3 5
5 6
6 7
7 8
7 16
8 9
9 11
9 12
**Output**
party group
1 g1
2 g1
3 g1
4 g1
5 g1
6 g1
7 g1
8 g1
9 g1
10 g1
11 g1
12 g1
16 g1
目前,我已经对同一表进行了 3 次左连接以跟踪数据直到 7 级。
sel columns
table a
left join table b
on a.related_party=b.party
left join table c
on b.related_party=c.party;
需要跟踪直到层次结构的末尾。因此,如果有人有任何其他技术,请提出建议。
你没有层次结构,你有一个"有向图"。您可以尝试先删除直接链接,然后再遍历层次结构。但是你必须能够确定一个根。
为了防止循环,您需要创建一个显示您以前的参与方的路径。
-- remove duplicates: A-B & B-A
CREATE VOLATILE TABLE tab AS (
SELECT DISTINCT party , related_party
FROM tab_org t1
WHERE NOT EXISTS(
SELECT * FROM tab_org t2
WHERE t1.related_party = t2.party
AND t1.party = t2.related_party
AND t1.related_party < t2.related_party
)
AND related_party <> party
) WITH DATA
ON COMMIT PRESERVE ROWS
;
-- now use the cleaner data
WITH RECURSIVE cte
AS
(
SELECT party, related_party, ROW_NUMBER() OVER (ORDER BY party) AS grp, CAST(TRIM(party) AS VARCHAR(10000)) AS PATH, 1 AS lvl
FROM tab AS t
WHERE NOT EXISTS
(
SELECT * FROM tab AS t2
WHERE t.party = t2.related_party
)
UNION ALL
SELECT tab.party,tab.related_party, grp,
cte.PATH || '.' || TRIM(tab.party), cte.lvl + 1
FROM cte JOIN tab
ON tab.party = cte.related_party
-- if new party is already in path it's a cycle
WHERE '.'||cte.PATH||'.' NOT LIKE '%.'||TRIM(tab.party)||'.%'
AND cte.lvl < 10 -- just in case, might be removed
)
SELECT *
FROM cte
ORDER BY path
如果没有周期,这将起作用,否则会更复杂。根据您的实际数据,您可能需要最终DISTINCT
。