Løsning
Sådan finder du noden med flest børn:
SELECT subpath(path, -1, 1), count(*) AS children
FROM tbl
WHERE path <> ''
GROUP BY 1
ORDER BY 2 DESC
LIMIT 1;
... og ekskluder rodnoder:
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
Forudsat at rodnoder har et tomt ltree
(''
) som vej. Måske NULL
. Brug derefter path IS NULL
...
Vinderen i dit eksempel er faktisk 2001
, med 5 børn.
Hvordan?
-
Brug funktionen
subpath(...)
leveret af ekstramoduletltree
. -
Hent den sidste node i stien med en negativ offset , som er den direkte overordnede for elementet.
-
Tæl hvor ofte den forælder optræder, ekskluder rodnoder og tag den resterende med det højeste antal.
-
Brug
ltree2text()
for at udtrække værdien fraltree
. -
Hvis flere noder har lige mange børn, vælges en vilkårlig i eksemplet.
Testcase
Dette er det arbejde, jeg skulle udføre for at komme til en nyttig testsag (efter at have trimmet noget støj):
Se SQLfiddle .
Med andre ord:husk venligst at give en nyttig testcase næste gang.
Yderligere kolonner
Svar til kommentar.
Udvid først testcasen:
ALTER TABLE tbl ADD COLUMN postal_code text
, ADD COLUMN whatever serial;
UPDATE tbl SET postal_code = (1230 + whatever)::text;
Tag et kig:
SELECT * FROM tbl;
Bare JOIN
resultat til det overordnede i basistabellen:
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;