Reputation: 451
I want to select all countries in Countries that can be found by recursively adding all neighbouring countries to the reachable countries already found by looking at the set that starts with just 'Sweden'. Basically, I have the set S which at the very beginning is the set {Sweden}, and select all names from the table borders
that are equal to the Country1 attribute while the Country2 attribute is in S, or are equal to the Country2 attribute while the Country1 attribute is in S. I modify S to this selected set. Then I keep doing this selection until I find no new countries that aren't in S.
By performing the selection on the table
Country1 Country2
----------------------
Sweden Finland
Norway Sweden
Norway Finland
Norway Russia
Russia Ukraine
Russia Finland
Russia China
Canada United States
I should get the result:
Name
----------------------
Finland
Norway
Russia
Ukraine
China
It's not the best but I hope that you get the idea of what I want to do. I'm using PostgreSQL.
Upvotes: 0
Views: 107
Reputation: 22811
Kind of (edited)
create table borders(
Country1 varchar(100),
Country2 varchar(100)
);
insert into borders(Country1,Country2)
values
('Sweden','Finland'),
('Norway','Sweden'),
('Norway','Finland'),
('Norway','Russia'),
('Russia','Ukraine'),
('Russia','Finland'),
('Russia','China'),
('Canada','United States')
;
WITH RECURSIVE neighbours AS (
-- start with 'Sweden' if any neighbour of it exists
SELECT DISTINCT 'Sweden' as Name, ARRAY[cast('Sweden' as varchar)] as path
FROM borders b
WHERE 'Sweden' IN (b.Country1, b.Country2)
--
UNION ALL
SELECT
CASE WHEN nb.Name = b.Country1 THEN b.Country2 ELSE b.Country1 END,
path || CASE WHEN nb.Name = b.Country1 THEN b.Country2 ELSE b.Country1 END
FROM borders b
JOIN neighbours nb ON nb.Name IN(b.Country1, b.Country2)
AND NOT(b.Country1 = ANY(path) AND b.Country2 = ANY(path))
)
SELECT DISTINCT Name
FROM neighbours;
Upvotes: 1