Решение
За да намерите възела с най-много деца:
SELECT subpath(path, -1, 1), count(*) AS children
FROM tbl
WHERE path <> ''
GROUP BY 1
ORDER BY 2 DESC
LIMIT 1;
... и изключете основните възли:
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
Ако приемем, че основните възли имат празно ltree
(''
) като път. Може да е NULL
. След това използвайте path IS NULL
...
Победителят във вашия пример всъщност е 2001
, с 5 деца.
Как?
-
Използвайте функцията
subpath(...)
предоставено от допълнителния модулltree
. -
Вземете последния възел в пътя с отрицателно отместване , който е пряк родител на елемента.
-
Пребройте колко често се появява този родител, изключете основните възли и вземете оставащия с най-голям брой.
-
Използвайте
ltree2text()
за да извлечете стойността отltree
. -
Ако множество възли имат еднакво най-много деца, в примера се избира произволен.
Тестов случай
Това е работата, която трябваше да свърша, за да стигна до полезен тестов случай (след отстраняване на малко шум):
Вижте SQLfiddle .
С други думи:моля, не забравяйте да предоставите полезен тестов случай следващия път.
Допълнителни колони
Отговорете на коментар.
Първо разгънете тестовия случай:
ALTER TABLE tbl ADD COLUMN postal_code text
, ADD COLUMN whatever serial;
UPDATE tbl SET postal_code = (1230 + whatever)::text;
Разгледайте:
SELECT * FROM tbl;
Просто JOIN
резултат на родителя в основната таблица:
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;