kge*_*geo 1 postgresql recursion parent-child aggregate-functions
在子-父表中,我需要汇总每个子项的所有父项。我可以很容易地在 CTE 查询中为每个父母获取孩子,但无法弄清楚如何反转它(这里是 sqfiddle)。鉴于这种:
CREATE TABLE rel(
child integer,
parent integer
);
INSERT INTO rel(child, parent)
VALUES
(1,NULL),
(2,1),
(3,1),
(4,3),
(5,2),
(6,4),
(7,2),
(8,7),
(9,8);
Run Code Online (Sandbox Code Playgroud)
将返回父数组的查询(顺序不重要):
1, {NULL}
2, {1}
3, {1}
4, {3,1}
5, {2,1}
6, {4,3,1}
7, {2,1}
8, {7,2,1}
9, {8,7,2,1}
Run Code Online (Sandbox Code Playgroud)
即使有一个公认的答案,我也想展示如何在纯 SQL 中以更简单的方式使用递归 CTE 解决问题:
WITH RECURSIVE t(child, parentlist) AS (
SELECT child , ARRAY[]::INTEGER[] FROM rel WHERE parent IS NULL
UNION
SELECT rel.child, rel.parent || t.parentlist
FROM rel
JOIN t ON rel.parent = t.child
) SELECT * FROM t;
child | parentlist
-------+------------
1 | {}
2 | {1}
3 | {1}
4 | {3,1}
5 | {2,1}
7 | {2,1}
6 | {4,3,1}
8 | {7,2,1}
9 | {8,7,2,1}
(9 rows)
Run Code Online (Sandbox Code Playgroud)
如果您坚持要{NULL}
为父母列表为空的孩子提供单身人士,请说
SELECT child,
CASE WHEN CARDINALITY(parentlist) = 0
THEN ARRAY[NULL]::INTEGER[]
ELSE parentlist
END
FROM t;
Run Code Online (Sandbox Code Playgroud)
而不是SELECT * FROM t
,但坦率地说,我不明白你为什么应该这样做。
最后一点:我不知道有什么有效的方法可以使用关系数据库来做到这一点,无论是使用纯 SQL 还是使用过程语言。关键是JOIN
's 本质上是昂贵的,如果您有非常大的表,您的查询将花费大量时间。您可以使用索引来缓解问题,但解决此类问题的最佳方法是使用图形软件而不是 RDBMS。
归档时间: |
|
查看次数: |
1304 次 |
最近记录: |