Řešení
Chcete-li najít uzel s největším počtem dětí:
SELECT subpath(path, -1, 1), count(*) AS children
FROM tbl
WHERE path <> ''
GROUP BY 1
ORDER BY 2 DESC
LIMIT 1;
... a vyloučit kořenové uzly:
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
Za předpokladu, že kořenové uzly mají prázdný ltree
(''
) jako cestu. Může být NULL
. Poté použijte path IS NULL
...
Vítěz ve vašem příkladu je ve skutečnosti 2001
, s 5 dětmi.
Jak?
-
Použijte funkci
subpath(...)
poskytuje doplňkový modulltree
. -
Získejte poslední uzel v cestě s záporným posunem , který je přímým rodičem prvku.
-
Spočítejte, jak často se tento rodič objevuje, vylučte kořenové uzly a vezměte zbývající s nejvyšším počtem.
-
Použijte
ltree2text()
extrahovat hodnotu zltree
. -
Pokud má více uzlů stejně nejvíce potomků, vybere se v příkladu libovolný.
Testovací případ
Toto je práce, kterou jsem musel udělat, abych se dostal k užitečnému testovacímu případu (po oříznutí nějakého šumu):
Viz SQLfiddle .
Jinými slovy:nezapomeňte prosím příště poskytnout užitečný testovací případ.
Další sloupce
Odpovězte na komentář.
Nejprve rozbalte testovací případ:
ALTER TABLE tbl ADD COLUMN postal_code text
, ADD COLUMN whatever serial;
UPDATE tbl SET postal_code = (1230 + whatever)::text;
Podívejte se:
SELECT * FROM tbl;
Jednoduše JOIN
výsledek k nadřazenému v základní tabulce:
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;