The SQL below gets ancestors in SQL Server using multiple recursive members, copied from an article by Itzik Ben-Gan in ITProToday back in 2013;
DROP TABLE IF EXISTS tmp_FamilyTree;
CREATE temporary TABLE tmp_FamilyTree
(
id INT NOT NULL CONSTRAINT PK_FamilyTree PRIMARY KEY,
name VARCHAR(30) NOT NULL,
mother INT NULL,
father INT NULL
);
INSERT INTO tmp_FamilyTree
(
id,
name,
mother,
father
)
VALUES
( 1,
'Balbo Baggins',
NULL,
NULL),
( 2,
'Berylla Boffin',
NULL,
NULL),
( 3,
'Mungo Baggins',
1,
2),
( 4,
'Laura Grubb',
NULL,
NULL),
( 5,
'Bungo Baggins',
3,
4),
( 6,
'Belladonna Took',
NULL,
NULL),
( 7,
'Bilbo Baggins',
5,
6),
( 8,
'Largo Baggins',
1,
2),
( 9,
'Tanta Hornblower',
NULL,
NULL),
( 10,
'Fosco Baggins',
8,
9),
( 11,
'Ruby Bolger',
NULL,
NULL),
( 12,
'Dora Baggins',
10,
11),
( 13,
'Drogo Baggins',
10,
11),
( 14,
'Dudo Baggins',
10,
11),
( 15,
'Primula Brandybuck',
NULL,
NULL),
( 16,
'Frodo Baggins',
13,
15);
WITH recursive C
AS ( -- anchor queries
-- father of input
SELECT father AS id,
1 AS lvl
FROM tmp_FamilyTree
WHERE id = 16
AND father IS NOT NULL
UNION ALL -- mother of input
SELECT mother AS id,
1 AS lvl
FROM tmp_FamilyTree
WHERE id = 16
AND mother IS NOT NULL
UNION ALL -- recursive queries
-- fathers of those in previous level
SELECT father AS id,
C.lvl + 1 AS lvl
FROM C
JOIN tmp_FamilyTree AS P ON C.id = P.id
WHERE P.father IS NOT NULL
UNION ALL -- fathers of those in previous level
SELECT mother AS id,
C.lvl + 1 AS lvl
FROM C
JOIN tmp_FamilyTree AS P ON C.id = P.id
WHERE P.mother IS NOT NULL)
SELECT C.id,
FT.name,
lvl
FROM C
JOIN tmp_FamilyTree AS FT ON C.id = FT.id;
When run in Postgres this throws error 'recursive reference to query "c" must not appear within its non-recursive term'. Running it in SQL Server, removing keywords recursive and Temporary, returns 8 rows. How can this be fixed in Postgres to also return 8 rows?