Recursive CTE for Tree Queries
Traverse hierarchical data like org charts and nested categories using PostgreSQL recursive common table expressions.
-- Table: categories (id, name, parent_id)
-- Get full category tree from a root node
WITH RECURSIVE category_tree AS (
-- Base case: start from root
SELECT id, name, parent_id, 0 AS depth, name::text AS path
FROM categories
WHERE parent_id IS NULL
UNION ALL
-- Recursive step: join children
SELECT c.id, c.name, c.parent_id, ct.depth + 1,
ct.path || ' > ' || c.name
FROM categories c
INNER JOIN category_tree ct ON c.parent_id = ct.id
WHERE ct.depth < 10 -- safety limit
)
SELECT id, name, depth, path
FROM category_tree
ORDER BY path;
-- Get all ancestors of a specific node
WITH RECURSIVE ancestors AS (
SELECT id, name, parent_id
FROM categories
WHERE id = 42 -- target node
UNION ALL
SELECT c.id, c.name, c.parent_id
FROM categories c
INNER JOIN ancestors a ON a.parent_id = c.id
)
SELECT * FROM ancestors;Use Cases
- Org chart navigation
- Nested category menus
- File system tree queries
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
Keyset Pagination vs Offset
Efficient keyset (cursor) pagination pattern compared to traditional OFFSET for large datasets in PostgreSQL.
UPSERT with ON CONFLICT
Insert or update rows atomically using PostgreSQL ON CONFLICT clause with partial indexes and conditions.
Full-Text Search with Ranking
PostgreSQL full-text search using tsvector, tsquery, and ts_rank with trigram similarity for fuzzy matching.
Window Functions with RANK and LAG
Use window functions to rank rows, calculate running totals, and compare with previous rows without self-joins.