Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Postgresql 如何从邻接列表中获取后代数组?_Postgresql - Fatal编程技术网

Postgresql 如何从邻接列表中获取后代数组?

Postgresql 如何从邻接列表中获取后代数组?,postgresql,Postgresql,我有下表和数据 CREATE TABLE relationships (a TEXT, b TEXT); CREATE TABLE nodes(n TEXT); INSERT INTO relationships(a, b) VALUES ('1', '2'), ('1', '3'), ('1', '4'), ('1', '5'), ('2', '6'), ('2', '7'), ('2', '8'), ('3', '9'); INSERT INTO nodes(n) VAL

我有下表和数据

CREATE TABLE relationships (a TEXT, b TEXT);
CREATE TABLE nodes(n TEXT);
INSERT INTO relationships(a, b) VALUES 
 ('1', '2'), 
 ('1', '3'),
 ('1', '4'),
 ('1', '5'),
 ('2', '6'),
 ('2', '7'),
 ('2', '8'),
 ('3', '9');
INSERT INTO nodes(n) VALUES ('1'), ('2'), ('3'), ('4'), ('5'), ('6'), ('7'), ('8'), ('9'), ('10');
我想要输出

  n  |  children
  1  |  ['2', '3', '4', '5', '6', '7', '8', '9']
  2  |  ['6', '7', '8', '9']
  3  |  ['9']
  4  |  []
  5  |  []
  6  |  []
  7  |  []
  8  |  []
  9  |  []
  10 |  []
我试图将
与RECURSIVE
结合使用,但仍停留在如何将参数传递到CTE上

WITH RECURSIVE traverse(n) AS (
    SELECT *
    FROM relationships
    WHERE a = n --- not sure how to pass data to here
    UNION ALL
    ...
)
WITH basic_cte AS (
    SELECT a1.n as n,
           (SELECT COALESCE(json_agg(temp), '[]')
            FROM (
                         (SELECT * FROM traverse(a1.a))
                 ) as temp
           ) as children
    FROM nodes as a1
)
SELECT *
FROM basic_cte;

注意:这将忽略所有空的子项。您可以像中一样添加左连接以获得该功能

除非转向存储过程等,否则无法将参数真正传递到CTE中。CTE是一个单独的表,需要包含您可能希望从中使用的所有行

假设一个相当好的图(没有重复的边,没有循环),下面这样的代码应该满足您的要求

  • 递归查询的基本情况是获取可能是父节点的所有节点的所有1级子节点(子节点)
  • 递归步骤沿树向下遍历第二级、第三级等
  • 一旦我们有了所有的父-子元组,我们就可以根据需要聚合数据

要获取所有节点的子节点的列表,需要向nodes表进行左联接

with recursive rels as (
  select a,b, a as root
  from relationships
  union all
  select c.*, r.root
  from relationships c
    join rels r on r.b = c.a
)
select n.n, array_agg(r.b) filter (where r.b is not null)
from nodes n
  left join rels r on r.root = n.n
group by n.n
order by n.n;

@汉斯马斯格雷夫:是的correct@a_horse_with_no_name我会改正的谢谢你非常感谢!这段代码提供了很多洞察,但它不会填充空的子项(我可以通过左连接实现这一点)哦,感谢您指出这一点!我应该更加注意期望的输出;)因为它似乎对你有一些价值,所以我将保持原样,只参考另一个答案。嗨,我刚刚在CTE上运行了解释分析。知道为什么估计的行数这么高吗<代码>(成本=21776.23..29537.83行=388080宽度=64)(实际时间=0.053..0.148行=12个循环=1)实际行数为12,但估计行数约为380k?我不知道这是从哪里来的,不运行查询就准确地估计递归行数通常是一个不可能的问题(即使对于非常简单的查询),因此postgres的错误在于根本不尝试。如果您有关于正在运行的查询的更多信息,您可能会得到一些帮助,例如帮助查询规划器解决问题
真空(分析)关系计划现在看起来不错:)谢谢!
with recursive rels as (
  select a,b, a as root
  from relationships
  union all
  select c.*, r.root
  from relationships c
    join rels r on r.b = c.a
)
select n.n, array_agg(r.b) filter (where r.b is not null)
from nodes n
  left join rels r on r.root = n.n
group by n.n
order by n.n;