PostgreSQL递归查询以获得排名边缘

问题描述 投票:1回答:1

我有一个表,表中有大量相互关联的边(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个回答
0
投票

您要遍历不同的(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 | result_1 | result_2:----------- | :--------- | -------:| -------:A | B | 1 | 1个B | C | 1 | 2C | D | 1 | 3E | F | 2 | 1个K | L | 3 | 1个L | M | 3 | 2
© www.soinside.com 2019 - 2024. All rights reserved.