Soluzione
Per trovare il nodo con più figli:
SELECT subpath(path, -1, 1), count(*) AS children
FROM tbl
WHERE path <> ''
GROUP BY 1
ORDER BY 2 DESC
LIMIT 1;
... ed escludi i nodi radice:
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
Supponendo che i nodi root abbiano un ltree
vuoto (''
) come percorso. Potrebbe essere NULL
. Quindi usa path IS NULL
...
Il vincitore nel tuo esempio è in realtà 2001
, con 5 bambini.
Come?
-
Usa la funzione
subpath(...)
fornito da il modulo aggiuntivoltree
. -
Ottieni l'ultimo nodo nel percorso con un offset negativo , che è il genitore diretto dell'elemento.
-
Conta la frequenza con cui appare quel genitore, escludi i nodi radice e prendi quello rimanente con il conteggio più alto.
-
Usa
ltree2text()
per estrarre il valore daltree
. -
Se più nodi hanno lo stesso numero di figli, nell'esempio ne viene scelto uno arbitrario.
Caso di prova
Questo è il lavoro che dovevo fare per arrivare a un utile test case (dopo aver tagliato un po' di rumore):
Vedi SQLfiddle .
In altre parole:ricordati di fornire un utile caso di prova la prossima volta.
Colonne aggiuntive
Rispondi al commento.
Innanzitutto, espandi il test case:
ALTER TABLE tbl ADD COLUMN postal_code text
, ADD COLUMN whatever serial;
UPDATE tbl SET postal_code = (1230 + whatever)::text;
Dai un'occhiata:
SELECT * FROM tbl;
Semplicemente JOIN
risultato al genitore nella tabella di base:
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;