Solución
Para encontrar el nodo con más hijos:
SELECT subpath(path, -1, 1), count(*) AS children
FROM tbl
WHERE path <> ''
GROUP BY 1
ORDER BY 2 DESC
LIMIT 1;
... y excluir los nodos raíz:
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
Suponiendo que los nodos raíz tienen un ltree
vacío (''
) como camino. Podría ser NULL
. Luego use path IS NULL
...
El ganador en tu ejemplo es en realidad 2001
, con 5 hijos.
¿Cómo?
-
Use la función
subpath(...)
proporcionada por el el módulo adicionalltree
. -
Obtener el último nodo en la ruta con un desplazamiento negativo , que es el padre directo del elemento.
-
Cuente con qué frecuencia aparece ese padre, excluya los nodos raíz y tome el restante con el conteo más alto.
-
Use
ltree2text()
para extraer el valor deltree
. -
Si varios nodos tienen la misma cantidad de hijos, se elige uno arbitrario en el ejemplo.
Caso de prueba
Este es el trabajo que tuve que hacer para llegar a un caso de prueba útil (después de recortar algo de ruido):
Ver SQLfiddle .
En otras palabras:recuerde proporcionar un caso de prueba útil la próxima vez.
Columnas adicionales
Responda al comentario.
Primero, expanda el caso de prueba:
ALTER TABLE tbl ADD COLUMN postal_code text
, ADD COLUMN whatever serial;
UPDATE tbl SET postal_code = (1230 + whatever)::text;
Echa un vistazo:
SELECT * FROM tbl;
Simplemente JOIN
resultado al padre en la tabla 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;