sql – 行使递归查询会见有向图,就仿佛它是一个无向图
副问题[/!--empirenews.page--]
我必要您关于会见存储在数据库中的有向图的辅佐. 请思量以下有向图 1->2 2->1,3 3->1 表存储这些相关: create database test; c test; create table ownership ( parent bigint,child bigint,primary key (parent,child) ); insert into ownership (parent,child) values (1,2); insert into ownership (parent,child) values (2,1); insert into ownership (parent,3); insert into ownership (parent,child) values (3,1); 我想提取从节点可达到的图形的全部半毗连边沿(即忽略偏向的毗连边沿).即,假如我从parent = 1开始,我想获得以下输出 1,2 2,1 2,3 3,1 我正在行使postgresql. 我已经修改了example on Postgres’ manual,它表明白递归查询,而且我已经调解了毗连前提以“向上”和“向下”(这样做我忽略了偏向).我的查询如下: c test WITH RECURSIVE graph(parent,child,path,depth,cycle) AS ( SELECT o.parent,o.child,ARRAY[ROW(o.parent,o.child)],false from ownership o where o.parent = 1 UNION ALL SELECT o.parent,path||ROW(o.parent,o.child),depth+1,ROW(o.parent,o.child) = ANY(path) from ownership o,graph g where (g.parent = o.child or g.child = o.parent) and not cycle ) select g.parent,g.child,g.path,g.cycle from graph g 其输出如下: parent | child | path | cycle --------+-------+-----------------------------------+------- 1 | 2 | {"(1,2)"} | f 2 | 1 | {"(1,2)","(2,1)"} | f 2 | 3 | {"(1,3)"} | f 3 | 1 | {"(1,"(3,1)"} | f 1 | 2 | {"(1,1)","(1,2)"} | t 1 | 2 | {"(1,3)",2)"} | t 3 | 1 | {"(1,1)"} | f 1 | 2 | {"(1,2)"} | t 2 | 3 | {"(1,3)"} | f 1 | 2 | {"(1,2)"} | t 2 | 3 | {"(1,3)"} | t 1 | 2 | {"(1,2)"} | t 3 | 1 | {"(1,1)"} | t (13 rows) 我有一个题目:查询多次提取沟通的边,由于它们通过差异的路径达到,我想停止这种环境.假如我将外部查询修改为 select distinct g.parent,g.child from graph 我有所需的功效,但在WITH查询中如故存在服从低下,由于不必要的毗连已完成. 我尚有另一个题目(这个题目已办理,请查察底部):正如您从输出中看到的那样,轮回仅在第二次达到节点时遏制.即我有(1,2)(2,3)(1,2). where (g.parent = o.child or g.child = o.parent) and (ROW(o.parent,o.child) <> any(path)) and not cycle 停止会见已会见的边沿,但它不起浸染,我无法领略为什么((ROW(o.parent,o.child)<>任何(路径))应该停止轮回再次进入轮回边沿可是不起浸染).如安在封锁轮回的节点之前遏制轮回一次? 编辑:正如danihp提议的,办理我行使的第二个题目 where (g.parent = o.child or g.child = o.parent) and not (ROW(o.parent,o.child) = any(path)) and not cycle 此刻输出不包括轮回.行从13变为6,但我如故有一再,以是提取全部边沿而没有一再且没有明明的首要(第一个)题目如故存在.当前输出有和不是ROW parent | child | path | cycle --------+-------+---------------------------+------- 1 | 2 | {"(1,2)"} | f 2 | 1 | {"(1,1)"} | f 2 | 3 | {"(1,3)"} | f 3 | 1 | {"(1,1)"} | f 3 | 1 | {"(1,1)"} | f 2 | 3 | {"(1,3)"} | f (6 rows) 编辑#2 ::遵循Erwin Brandstetter的提议,我修改了我的查询,可是假如我没有错,提议的查询会提供比我更多的行(ROW较量如故存在,由于它对我来说好像更清晰,纵然我领略字符串较量会更有服从). WITH RECURSIVE graph(parent,depth) AS ( SELECT o.parent,0 from ownership o where 1 in (o.child,o.parent) UNION ALL SELECT o.parent,depth+1 from ownership o,graph g where g.child in (o.parent,o.child) and ROW(o.parent,o.child) <> ALL(path) ) select g.parent,g.child from graph g 编辑3:以是,正如Erwin Brandstetter指出的那样,最后一个查询如故是错误的,而正确的查询可以在他的答复中找到. 当我宣布我的第一个查询时,我没有领略我错过了一些毗连,由于它产生在以下环境:假如我从节点3开始,db选择行(2,3)和(3,1) ).然后,查询的第一个归纳步调将从这些行中选择行(1,2),(2,1),从而穷乏应包括在个中的行(2,1).功效在观念上算法意味着((2,1)是“靠近”(3,1)) 当我实行在Postgresql手册中修改示例时,我正好实行插手全部权的怙恃和孩子,但我错了没有生涯必需在每个步调中插手的图的值. 这些范例的查询好像按照起始节点天生差异的行集(即,取决于在根基步调中选择的行集).因此,我以为在根基步调中只选择包括起始节点的一行也许很有效,由于无论怎样您将得到任何其他“相邻”节点. 办理要领可以像这样事变:WITH RECURSIVE graph AS ( SELECT parent,',' || parent::text || ',' || child::text || ',' AS path,0 AS depth FROM ownership WHERE parent = 1 UNION ALL SELECT o.parent,g.path || o.child || ',g.depth + 1 FROM graph g JOIN ownership o ON o.parent = g.child WHERE g.path !~~ ('%,' || o.parent::text || ',' || o.child::text || ',%') ) SELECT * FROM graph 你提到了机能,以是我在这个偏向长举办了优化. 首要概念: >仅在界说的偏向上遍历图形.
(编辑:湖南网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |