Solution
To find the node with the most children:
SELECT subpath(path, -1, 1), count(*) AS children
FROM tbl
WHERE path <> ''
GROUP BY 1
ORDER BY 2 DESC
LIMIT 1;
... and exclude root nodes:
SELECT *
FROM (
SELECT ltree2text(subpath(path, -1, 1))::int AS tbl_id, count(*) AS children
FROM tbl
WHERE path <> ''
GROUP BY 1
) ct
LEFT JOIN (
SELECT tbl_id
FROM tbl
WHERE path = ''
) x USING (tbl_id)
WHERE x.tbl_id IS NULL
ORDER BY children DESC
LIMIT 1
Assuming that root nodes have an empty ltree
(''
) as path. Might be NULL
. Then use path IS NULL
...
The winner in your example is actually 2001
, with 5 children.
How?
Use the function
subpath(...)
provided by the the additional moduleltree
.Get the last node in the path with a negative offset, which is the direct parent of the element.
Count how often that parent appears, exclude root nodes and take the remaining one with the highest count.
Use
ltree2text()
to extract the value fromltree
.If multiple nodes have equally the most children an arbitrary one is picked in the example.
Test case
This is the work I had to do to get to a useful test case (after trimming some noise):
See SQLfiddle.
In other words: please remember to provide a useful test case next time.
Additional columns
Answer to comment.
First, expand the test case:
ALTER TABLE tbl ADD COLUMN postal_code text
, ADD COLUMN whatever serial;
UPDATE tbl SET postal_code = (1230 + whatever)::text;
Have a look:
SELECT * FROM tbl;
Simply JOIN
result to the parent in the base table:
SELECT ct.*, t.postal_code
FROM (
SELECT ltree2text(subpath(path, -1, 1))::int AS tbl_id, count(*) AS children
FROM tbl
WHERE path <> ''
GROUP BY 1
) ct
LEFT JOIN (
SELECT tbl_id
FROM tbl
WHERE path = ''
) x USING (tbl_id)
JOIN tbl t USING (tbl_id)
WHERE x.tbl_id IS NULL
ORDER BY children DESC
LIMIT 1;