在子父表中,我需要汇总每个孩子的所有父母。我可以很容易地在CTE查询中获得每个父项的子项,但无法计算如何反转它(sqfiddle here)。鉴于此:
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);
将返回父项数组的查询(顺序并不重要):
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}
答案 0 :(得分:3)
即使有一个可接受的答案,我想展示如何用更简单的方式在纯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)
如果您坚持为父母列表空白的孩子设置单身{NULL}
,请说
SELECT child,
CASE WHEN CARDINALITY(parentlist) = 0
THEN ARRAY[NULL]::INTEGER[]
ELSE parentlist
END
FROM t;
而不是SELECT * FROM t
,但坦率地说,我不明白为什么你应该这样做。
最后一句话:我不知道有任何有效的方法可以用纯SQL或过程语言来处理关系数据库。关键是JOIN
本来就很昂贵,如果你有非常大的表,你的查询会花费很多时间。您可以通过索引缓解问题,但解决此类问题的最佳方法是使用图形软件而不是RDBMS。
答案 1 :(得分:2)
为此你*可以创建一个PL。我做了类似的事情,这是我的PL处理任何父子结构,它返回一个表,但对于你的情况我改变了一点:
DROP FUNCTION IF EXISTS ancestors(text,integer,integer);
CREATE OR REPLACE FUNCTION ancestors(
table_name text,
son_id integer,-- the id of the son you want its ancestors
ancestors integer)-- how many ancestors you want. 0 for every ancestor.
RETURNS integer[]
AS $$
DECLARE
ancestors_list integer[];
father_id integer:=0;
query text;
row integer:=0;
BEGIN
LOOP
query:='SELECT child, parent FROM '||quote_ident(table_name) || ' WHERE child='||son_id;
EXECUTE query INTO son_id,father_id;
RAISE NOTICE 'son:% | father: %',son_id,father_id;
IF son_id IS NOT NULL
THEN
ancestors_list:=array_append(ancestors_list,father_id);
son_id:=father_id;
ELSE
ancestors:=0;
father_id:=0;
END IF;
IF ancestors=0
THEN
EXIT WHEN father_id IS NULL;
ELSE
row:=row+1;
EXIT WHEN ancestors<=row;
END IF;
END LOOP;
RETURN ancestors_list;
END;
$$ LANGUAGE plpgsql;
创建PL后,要获得wat,您只需查询:
SELECT *,ancestors('rel',child,0) from rel
返回:
child | parent | ancestors
------+--------+-----------------
1 | NULL | {NULL}
2 | 1 | {1,NULL}
3 | 1 | {1,NULL}
4 | 3 | {3,1,NULL}
5 | 2 | {2,1,NULL}
6 | 4 | {4,3,1,NULL}
7 | 2 | {2,1,NULL}
8 | 7 | {7,2,1,NULL}
9 | 8 | {8,7,2,1,NULL}
如果您不想出现NULL,只需更新PL;)