Lösning
Så här hittar du noden med flest barn:
SELECT subpath(path, -1, 1), count(*) AS children
FROM tbl
WHERE path <> ''
GROUP BY 1
ORDER BY 2 DESC
LIMIT 1;
... och exkludera rotnoder:
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
Förutsatt att rotnoder har ett tomt ltree
(''
) som väg. Kan vara NULL
. Använd sedan path IS NULL
...
Vinnaren i ditt exempel är faktiskt 2001
, med 5 barn.
Hur?
-
Använd funktionen
subpath(...)
tillhandahålls av tilläggsmodulenltree
. -
Hämta den sista noden i sökvägen med en negativ offset , som är den direkta föräldern till elementet.
-
Räkna hur ofta den föräldern visas, exkludera rotnoder och ta den återstående med det högsta antalet.
-
Använd
ltree2text()
för att extrahera värdet frånltree
. -
Om flera noder har lika många barn väljs en godtycklig i exemplet.
Testfall
Det här är arbetet jag var tvungen att göra för att komma till ett användbart testfall (efter att ha trimmat lite brus):
Se SQLfiddle .
Med andra ord:kom ihåg att ge ett användbart testfall nästa gång.
Ytterligare kolumner
Svar på kommentar.
Utöka först testfallet:
ALTER TABLE tbl ADD COLUMN postal_code text
, ADD COLUMN whatever serial;
UPDATE tbl SET postal_code = (1230 + whatever)::text;
Ta en titt:
SELECT * FROM tbl;
JOIN
resultat till det överordnade i bastabellen:
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;