Lets say I have a table with Nodes and one table with Links that lets you create a link between two Nodes. How do I get the whole "web" of Nodes from just one Node ID? I have tried to visualize my problem like this:
As you can see, the Links don't form a chain like a linked list so a normal recursive query does not return all the Nodes in this web. If I start with ID 1, it will only return: 1, 2 and 3.
UPDATE : example with simple recursive query and sample data
WITH RECURSIVE links AS (
SELECT 1 AS id_from, 2 AS id_to
UNION
SELECT 2 AS id_from, 3 AS id_to
UNION
SELECT 4 AS id_from, 3 AS id_to
), web AS (
SELECT
l.id_from,
l.id_to
FROM
links AS l
WHERe
id_from = 1
UNION ALL
SELECT
l.id_from,
l.id_to
FROM
links AS l
jOIN web ON l.id_from = web.id_to
)
SELECT
*
FROM
web
OUTPUT:
id_from |id_to
________________
1 | 2
2 | 3
What I would like is for the link between 4 and 3 to be included in the result.
UPDATE 2: what I am trying to achieve:
I am creating a web app without user registration. Each device is given a unique ID, but I want to make it possible to recognize a user across several devices/browsers. For this to be possible the user must be able to link their devices together. Each user will have their own cluster of device IDs like in the image above. The reason I need this query is so that I can retrieve all the devices in the cluster using any of the linked devices IDs.
Cyclic vs acyclic: I will not allow links between two nodes that are aleary apart of the cluster, will this make the graph acyclic?
Try this. I didn't test it so much, take it as a starting point:
WITH RECURSIVE links0 AS (
SELECT 1 AS id_from, 2 AS id_to
UNION
SELECT 2 AS id_from, 3 AS id_to
UNION
SELECT 4 AS id_from, 3 AS id_to
), links as (
select id_from, id_to from links0 union select id_to, id_from from links0
), web (id_from,id_to,seen) AS (
SELECT
l.id_from,
l.id_to,
array[least(l.id_from,l.id_to)||'-'||greatest(l.id_from,l.id_to)]
FROM
links AS l
WHERe
id_from = 1
UNION ALL
SELECT
l.id_from,
l.id_to,
web.seen || (least(l.id_from,l.id_to)||'-'||greatest(l.id_from,l.id_to))
FROM
links AS l
jOIN web ON l.id_from = web.id_to
and not (least(l.id_from,l.id_to)||'-'||greatest(l.id_from,l.id_to) = any(web.seen))
)
SELECT
*
FROM
web
The links
CTE has edges reversed, then the seen
array keeps visited edges in canonical form.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.