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

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

我有一个表,其中有大量的边,这些边在某种程度上彼此相关(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

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

感谢您的帮助!

最佳答案

您想要遍历不同的(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 |        2
C            | D          |        1 |        3
E            | F          |        2 |        1
K            | L          |        3 |        1
L            | M          |        3 |        2

关于sql - PostgreSQL 递归查询以获得排名边缘,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62272142/

相关文章:

algorithm - 使用次优解决方案采访调度算法

algorithm - 如何在3d空间中使用Prims算法

algorithm - 打印二叉树的边界

mysql - JPQL,搜索值是否为 IN 或 NULL

mysql - 如何使用索引在两列之间进行查询过滤

mysql - 通过链接的 MySQL 数据库更新 MySQL 数据库的 MSSQL

mysql - 处理 SQL 保留表名和列名

sql - 每组匹配行的比率

postgresql - 具有动态参数的postgres存储过程中的语法错误

postgresql - 在 sqlalchemy 中提交之前运行清理/验证代码