Note: with help from RhodiumToad on #postgresql, I\'ve arrived at a solution, which I posted as answer. If anyone can improve on this, please chime in!
I have not be
I see two problems with the query:
the non-recursive part does not specify the root node. You need to either explicitely select that using WHERE descendant_node_id = 14 or "dynamically" using:
SELECT ..
FROM node_relations nr1
WHERE NOT EXISTS (SELECT 1
FROM node_relations nr2
WHERE nr2.ancestor_node_id = nr1.descendant_node_id)
with the correct starting point, the path is not complete as it will miss the final node during the aggregation in the recursive part. So in the outer query you need to append ancestor_node_id to the generated path.
So the query would look like this:
WITH RECURSIVE node_graph AS (
SELECT nr1.id, nr1.ancestor_node_id, nr1.descendant_node_id, ARRAY[nr1.descendant_node_id] AS path, 0 as level
FROM node_relations nr1
WHERE NOT EXISTS (SELECT 1
FROM node_relations nr2
WHERE nr2.ancestor_node_id = nr1.descendant_node_id)
UNION ALL
SELECT nr.id, nr.ancestor_node_id, nr.descendant_node_id, nr.descendant_node_id || ng.path, ng.level + 1 as level
FROM node_relations nr
JOIN node_graph ng ON ng.ancestor_node_id = nr.descendant_node_id
)
SELECT ancestor_node_id||path as path, -- add the last element of the sub-tree to the path
level as depth
FROM node_graph
ORDER BY level
Here is the SQLFiddle: http://sqlfiddle.com/#!15/e646b/3