问题描述
我有一个节点表
Table Node
Column| type
------|---------------
id | int
x | int
y | int
z | text
例如,
id | x | y | z
---|---|---|---
0 | 0 | 0 |'a'
1 | 0 | 1 |'b'
2 | 1 | 0 |'c'
3 | 1 | 1 |'d'
和
Table Edge
Column| type
------|---------------
source| int references Node.id
target| int references Node.id
例如,
source | target
-------|-------
0 | 1
1 | 3
3 | 2
假设节点本身没有优势,并且每个来源都是唯一的
我想显示整个边缘信息的结果
source.x | source.y | target.x | target.y
---------|----------|----------|---------
0 | 0 | 0 | 1
0 | 1 | 1 | 1
1 | 1 | 1 | 0
我尝试了很多联接(节点的自我联接与带有边的内部联接),(边缘的左联接与节点的自我联接的结果)
如何获得选择结果?
解决方法
我认为您想要两个联接:
select ns.x,ns.y,nt.x,nt.y
from edge e join
nodes n1
on e.source = ns.id join
nodes nd
on e.target = nt.id
,
对于PostgreSQL,可以使用RECURSIVE WITH
子句。
a)建立路径:
CREATE LOCAL TEMPORARY TABLE
node(id,x,y,z) AS (
SELECT 0,'a'
UNION ALL SELECT 1,1,'b'
UNION ALL SELECT 2,'c'
UNION ALL SELECT 3,'d'
)
;
CREATE LOCAL TEMPORARY TABLE
edge(source,target) AS (
SELECT 0,1
UNION ALL SELECT 1,3
UNION ALL SELECT 3,2
)
;
WITH RECURSIVE backbone AS (
SELECT
source::CHAR(1)||','||target::CHAR(1) AS path,1 AS hops,*
FROM edge
UNION ALL SELECT
p.path||','||c.target::CHAR(1) AS path,p.hops + 1 AS hops,c.*
FROM backbone p JOIN edge c ON c.source=p.target
)
SELECT * FROM backbone;
path | hops | source | target
---------+------+--------+--------
0,1 | 1 | 0 | 1
1,3 | 1 | 1 | 3
3,2 | 1 | 3 | 2
0,3 | 2 | 1 | 3
1,3,2 | 2 | 3 | 2
0,2 | 3 | 3 | 2
b)对于具有2跳和3跳的路径,请从路径中获取第一个和最后一个节点ID:
-- as above,but instead of the last line: "SELECT * FROM backbone" ...,origin_and_dest AS (
SELECT
*,SPLIT_PART(path,',1 )::INT AS origin,hops + 1)::INT AS destination
FROM backbone
WHERE hops >=2
)
SELECT * FROM origin_and_dest;
path | hops | source | target | origin | destination
---------+------+--------+--------+--------+-------------
0,3 | 2 | 1 | 3 | 0 | 3
1,2 | 2 | 3 | 2 | 1 | 2
0,2 | 3 | 3 | 2 | 0 | 2
在路径中没有最终源ID和最终目标ID的情况下,请重新加入节点:
-- same as above,but instead of the last line: "SELECT * FROM origin_and_dest" ...
SELECT
origin.x AS source_x,origin.y AS source_y,dest.x AS target_y,dest.y AS target_y
FROM origin_and_dest
JOIN node AS origin ON origin=origin.id
JOIN node AS dest ON destination=dest.id
;
source_x | source_y | target_y | target_y
----------+----------+----------+----------
0 | 0 | 1 | 0
0 | 0 | 1 | 1
0 | 1 | 1 | 0
您的结果并不完全,但是我真的不知道您所说的“整个边缘信息”是什么意思……您能更精确吗?