# 构造样本数据

``````-- 每一条有向关系边都存在上游，下游两个节点
drop table if exists demo.t_rel;
create table if not exists demo.t_rel(up int , down int);

-- 唯一约束，避免插入相同的关系
alter table demo.t_rel add constraint udx_t_rel unique (up, down);

insert into demo.t_rel values(6,5),(3,7),(5,1),(1,2),(5,2),(5,7),(7,2),(2,4),(7,4);

-- 构造一条环数据，7-2-4-7
delete from demo.t_rel where up=4 and down=7;
insert into demo.t_rel values(4,7);

# 递归查询

## 指定节点的下级

• 使用数组保存当前的路径信息。
• 计算下一个节点之前，判断该节点是否已经存在于路径上。如果是，就说明该点是环的起点，必须排除这个节点来达到破环的效果。
• 起始节点和最大深度，都是可选的。如果忽略这两个条件，就会返回完整的图信息。
``````with recursive
downstream as
(
select 1 as lvl, r.up, r.down,
-- 保存当前路径
array[]::int[] || r.up || r.down as trace
from demo.t_rel r
where r.up = 7 -- 指定起点
union all
select ds.lvl +1, r.up, r.down, ds.trace || r.down
from demo.t_rel r , downstream ds
where r.up = ds.down
-- 破环
and not r.down = any(ds.trace)
and ds.lvl < 20 -- 最大深度
)
select * from downstream ds;

``````-- 可以看到并没有包括7-2-4-7这条环。
lvl | up | down |  trace
-----+----+------+---------
1 |  7 |    2 | {7,2}
1 |  7 |    4 | {7,4}
2 |  2 |    4 | {7,2,4}
(3 rows)

## 指定节点的所有关联

``````drop function if exists f_get_rel;

/*

@start_node 起始节点。
@direct_flag 查询方向，-1：查找上级；1：查找下级； 0：查找上下级；
@max_depth 递归深度，即查找最多几级关系。
*/
create or replace function f_get_rel(start_node int, direct_flag int=1, max_depth int=20)
returns table (direct int, cur_depth int, up_node int, down_node int, trace int[])
as ?
begin

return query
with recursive
downstream as
(
select 1 as lvl, r.up, r.down, array[]::int[] || r.up || r.down as trace
from demo.t_rel r
where r.up = start_node
and direct_flag in (0, 1)
union all
select ds.lvl +1, r.up, r.down, ds.trace || r.down
from demo.t_rel r , downstream ds
where r.up = ds.down
and not r.down = any(ds.trace)
and ds.lvl < max_depth
),
upstream as
(
select 1 as lvl, r.up, r.down, array[]::int[] || r.up || r.down as trace
from demo.t_rel r
where r.down = start_node
and direct_flag in (0, -1)
union all
select us.lvl +1, r.up, r.down, r.up || us.trace
from demo.t_rel r , upstream us
where r.down = us.up
and not r.up = any(us.trace)
and us.lvl < max_depth
)
select -1, us.* from upstream us
union all
select 1, ds.* from downstream ds
order by 1 desc, lvl, up, down
;

end;
? language plpgsql strict;

``````dap=# select * from demo.f_get_rel(7,0,3);
direct | cur_depth | up_node | down_node |   trace
--------+-----------+---------+-----------+-----------
1 |         1 |       7 |         2 | {7,2}
1 |         1 |       7 |         4 | {7,4}
1 |         2 |       2 |         4 | {7,2,4}
-1 |         1 |       3 |         7 | {3,7}
-1 |         1 |       4 |         7 | {4,7}
-1 |         1 |       5 |         7 | {5,7}
-1 |         2 |       2 |         4 | {2,4,7}
-1 |         2 |       6 |         5 | {6,5,7}
-1 |         3 |       1 |         2 | {1,2,4,7}
-1 |         3 |       5 |         2 | {5,2,4,7}
(10 rows)

# 图形显示结果

## ECharts模板

``````option = {
title: {
text: '数据图谱'
},
tooltip: {},
animationDurationUpdate: 1500,
animationEasingUpdate: 'quinticInOut',
series : [
{
type: 'graph',
layout: 'force',
force: {
repulsion: 1000
},
symbolSize: 30,
roam: true,
label: {
normal: {
show: true
}
},
edgeSymbol: ['circle', 'arrow'],
edgeSymbolSize: [4, 10],
edgeLabel: {
normal: {
textStyle: {
fontSize: 20
}
}
},
data: [
{ name:"2", draggable: true, symbolSize:20},
],
{ source:"2", target:"4"},
],

}
]
};

## 构造显示用数据

``````-- 根据节点的关联点数量，设置图形大小
with rel as (select * from f_get_rel(7,0,2)),
up_nodes as (select up_node, count(distinct down_node) as out_cnt from rel group by up_node),
down_nodes as (select down_node, count(distinct up_node) as in_cnt from rel group by down_node),
node_cnt as ( select up_node as node, out_cnt as cnt from up_nodes union all select * from down_nodes )
select '{ name:"' || n.node || '", draggable: true, symbolSize:' || sum(n.cnt) * 10 || '},'  as node
from node_cnt n
group by n.node
order by 1;

``````select distinct r.up_node, r.down_node, '{ source:"'|| r.up_node ||'", target:"'|| r.down_node ||'"},' as links
from f_get_rel(7,0,3) r
order by r.up_node	;

## 图形显示

• 查询节点7的所有2度关联节点信息，结果显示如下

• 查询节点7的所有关联节点信息（不限层级数），结果显示如下