【问题标题】:Aggregating connected sets of nodes / edges聚合连接的节点/边集
【发布时间】:2015-04-29 18:01:44
【问题描述】:

我有一组具有唯一节点的连接边。它们使用父节点连接。考虑以下示例代码和插图:

CREATE TABLE network (
  node integer PRIMARY KEY,
  parent integer REFERENCES network(node),
  length numeric NOT NULL
);
CREATE INDEX ON network (parent);
INSERT INTO network (node, parent, length) VALUES
  (1, NULL, 1.3),
  (2, 1, 1.2),
  (3, 2, 0.9),
  (4, 3, 1.4),
  (5, 4, 1.6),
  (6, 2, 1.5),
  (7, NULL, 1.0);

在视觉上,可以识别出两组边缘。如何使用 PostgreSQL 9.1 和length 来识别这两个组?显示预期结果:

 edges_in_group | total_edges | total_length
----------------+-------------+--------------
 {1,2,3,4,5,6}  |           6 |          7.9
 {7}            |           1 |          1.0
(2 rows)

我什至不知道从哪里开始。我需要自定义聚合或窗口函数吗?我可以使用WITH RECURSIVE 迭代地收集连接的边吗?我的真实案例是一个有 245,000 条边的流网络。我预计edges_in_group 的最大数量少于 200,以及几百个聚合组(行)。

【问题讨论】:

    标签: postgresql aggregate common-table-expression recursive-query window-functions


    【解决方案1】:

    递归查询是要走的路:

    with recursive tree as (
      select node, parent, length, node as root_id
      from network
      where parent is null
      union all
      select c.node, c.parent, c.length, p.root_id
      from network c
        join tree p on p.node = c.parent
    )
    select root_id, array_agg(node) as edges_in_group, sum(length) as total_length
    from tree
    group by root_id;
    

    重要的是在每次递归中保留根节点的id,这样你就可以在最终结果中按那个id分组。

    【讨论】:

    • 这是一个非常快速简单的方法!在一个真实的例子中可以很好地扩展。
    猜你喜欢
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-21
    • 1970-01-01
    相关资源
    最近更新 更多