Skip to content

Instantly share code, notes, and snippets.

@vpetrigo
Last active July 18, 2023 04:35
Show Gist options
  • Save vpetrigo/854cb732e6036b17b2ce to your computer and use it in GitHub Desktop.
Save vpetrigo/854cb732e6036b17b2ce to your computer and use it in GitHub Desktop.
Generate nested set structure from PostgreSQL ltree structure
CREATE VIEW anc_and_des AS
SELECT
m.*,
-- Count all descendats of a vertice
( SELECT COUNT(*)
FROM KeywordLtree AS d
WHERE m.path @> d.path
) AS descendants,
-- Count all ancestors of a vertice
( SELECT COUNT(*)
FROM KeywordLtree AS a
WHERE a.path @> m.path
) AS ancestors,
-- Enumerate vertices as with DFS flow
ROW_NUMBER() OVER (ORDER BY m.path) AS rn
FROM KeywordLtree AS m;
-- Generate output:
-- left index for a vertice would be a 2 * number of a vertice in DFS - ancestros
-- right index for a vertice would be a left index + 2 * number of descendats - 1 (because without -1 we
-- would count current vertice twice
SELECT '#', id, value, 2 * rn - ancestors AS lft, 2 * rn - ancestors + 2 * descendants - 1 AS rgt
FROM anc_and_des
ORDER BY lft;
WITH aux AS (
SELECT A.id, A.value, A.path, COUNT(*) as size, ROW_NUMBER(*) OVER(ORDER BY A.path) as ord
FROM KeywordLtree A, KeywordLtree B
WHERE A.path @> B.path
GROUP BY A.id, A.value, A.path
)
SELECT '#', id, value, 1 + (ord - 1) * 2 - nlevel(path) as lft, (ord + size - 1) * 2 - nlevel(path) as rgt
FROM aux;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment