【问题标题】:PostgreSQL recursive query in order to get ranked edgesPostgreSQL递归查询以获得排名边缘
【发布时间】:2020-06-08 22:25:52
【问题描述】:

我有一张表,其中包含大量相互关联的边(from_segment 和 to_segment)。每条边都分为几个不同的较小扇区(from_meter 和 to_meter)。每个较小的扇区都有一个指定的方向。

见下表:

DROP TABLE IF EXISTS network;
CREATE TABLE network (
  id integer PRIMARY KEY,
  from_segment text,
  to_segment text, 
  from_meter int,
  to_meter int,
  direction text
);

INSERT INTO network (id, from_segment, to_segment, from_meter, to_meter, direction) VALUES
  (1,'A', 'B', 0, 5,'X'),
  (2,'A', 'B', 0, 5,'Y'),
  (3,'A', 'B', 5,10,'X'),
  (4,'A', 'B', 5,10,'Y'),
  (5,'A', 'B',10,15,'X'),
  (6,'A', 'B',10,15,'Y'),
  (7,'A', 'B',15,20,'X'),
  (8,'A', 'B',15,20,'Y'),

  (9,'B', 'C', 0, 5,'X'),
  (10,'B', 'C', 0, 5,'Y'),
  (11,'B', 'C', 5,10,'X'),
  (12,'B', 'C', 5,10,'Y'),
  (13,'B', 'C',10,15,'X'),
  (14,'B', 'C',10,15,'Y'),
  (15,'B', 'C',15,20,'X'),
  (16,'B', 'C',15,20,'Y'),

  (17,'C', 'D', 0, 5,'X'),
  (18,'C', 'D', 0, 5,'Y'),
  (19,'C', 'D', 5,10,'X'),
  (20,'C', 'D', 5,10,'Y'),
  (21,'C', 'D',10,15,'X'),
  (22,'C', 'D',10,15,'Y'),

  (23,'E', 'F', 0, 5,'X'),
  (24,'E', 'F', 0, 5,'Y'),
  (25,'E', 'F', 5,10,'X'),
  (26,'E', 'F', 5,10,'Y'),

  (27,'K', 'L', 0, 5,'X'),
  (28,'K', 'L', 0, 5,'Y'),
  (29,'K', 'L', 5,10,'X'),
  (30,'K', 'L', 5,10,'Y'),
  (31,'K', 'L',10,15,'X'),
  (32,'K', 'L',10,15,'Y'),

  (33,'L', 'M', 0, 5,'X'),
  (34,'L', 'M', 0, 5,'Y');

我想做的是将边缘(也适用于每个较小的部门和方向)带入特定的等级/顺序:

from_segment| to_segment | result_1 | result_2
     A            B           1         1 
     B            C           1         2
     C            D           1         3
     E            F           2         1
     K            L           3         1
     L            M           3         2

我尝试使用几种不同的方法完成查询,例如递归函数以及分区方法,但我每次都失败了。我想解决方案介于两者之间,但我不知道如何解决这个问题。

感谢您的帮助!

【问题讨论】:

    标签: sql postgresql graph-algorithm window-functions recursive-query


    【解决方案1】:

    您想要遍历不同的 (from_segment, to_segmgent) 元组,同时对路径和每条路径上的节点进行编号。

    这个递归查询应该做你想做的事:

    with recursive
        data as (
            select distinct from_segment, to_segment from network
        ),
        rcte as (
            select 
                from_segment, 
                to_segment, 
                row_number() over(order by from_segment) result_1,
                1 result_2
            from data d
            where not exists (
                select 1 from data d1 where d1.to_segment = d.from_segment
            )
            union all
            select  
                d.from_segment,
                d.to_segment,
                r.result_1,
                r.result_2 + 1
            from rcte r
            inner join data d on d.from_segment = r.to_segment
        )
    select * from rcte order by result_1, result_2
    

    第一个 cte 列出了不同的元组;然后递归 cte 从每条路径的开头开始,用row_number() 对它们进行排序,然后遍历每条路径,沿途增加一个计数器。

    Demo on DB Fiddle

    from_segment | to_segment |结果_1 |结果_2 :----------- | :--------- | --------: | --------: 一个 |乙| 1 | 1 乙| C | 1 | 2 C | D | 1 | 3 E | F | 2 | 1 ķ |大号 | 3 | 1 大号 |中号 | 3 | 2

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-01
      • 1970-01-01
      相关资源
      最近更新 更多