Solution
Pour trouver le nœud avec le plus d'enfants :
SELECT subpath(path, -1, 1), count(*) AS children
FROM tbl
WHERE path <> ''
GROUP BY 1
ORDER BY 2 DESC
LIMIT 1;
... et exclure les nœuds racine :
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
En supposant que les nœuds racine ont un ltree
vide (''
) comme chemin. Peut être NULL
. Ensuite, utilisez path IS NULL
...
Le gagnant dans votre exemple est en fait 2001
, avec 5 enfants.
Comment ?
-
Utilisez la fonction
subpath(...)
fourni par le module supplémentaireltree
. -
Obtenir le dernier nœud dans le chemin avec un décalage négatif , qui est le parent direct de l'élément.
-
Comptez la fréquence d'apparition de ce parent, excluez les nœuds racine et prenez celui qui reste avec le nombre le plus élevé.
-
Utilisez
ltree2text()
pour extraire la valeur deltree
. -
Si plusieurs nœuds ont également le plus d'enfants, un nœud arbitraire est choisi dans l'exemple.
Cas de test
C'est le travail que j'ai dû faire pour arriver à un cas de test utile (après avoir coupé un peu de bruit):
Voir SQLfiddle .
En d'autres termes :n'oubliez pas de fournir un scénario de test utile la prochaine fois.
Colonnes supplémentaires
Répondez au commentaire.
Tout d'abord, développez le cas de test :
ALTER TABLE tbl ADD COLUMN postal_code text
, ADD COLUMN whatever serial;
UPDATE tbl SET postal_code = (1230 + whatever)::text;
Jetez un œil :
SELECT * FROM tbl;
Simplement JOIN
résultat au parent dans la table de 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;