Photo by Joaquín Rivero on Unsplash
How to Manage and Query Hierarchical Data with the Adjacency Model in PostgreSQL
Using the Adjacency Model in PostgreSQL for Hierarchical Data Management and Queries
The adjacency model is a common way to represent hierarchical data in a relational database system like PostgreSQL. It involves storing each entry in a table along with a reference to its parent. This approach is straightforward and allows for easily adding and removing nodes. However, querying can become complex and slow if the hierarchy depth increases significantly, because it often requires recursive queries.
Here’s how you can implement and use the adjacency model in PostgreSQL, including how to create the table, insert data, and query the hierarchical data.
Step 1: Creating the Table
First, let’s create a simple table to represent a hierarchy such as a corporate organization structure or a category tree. Each row in the table will represent a node, and there will be a column to reference the parent node.
CREATE TABLE categories (
category_id SERIAL PRIMARY KEY,
category_name VARCHAR(255),
parent_id INTEGER,
FOREIGN KEY (parent_id) REFERENCES categories(category_id)
);
In this example, category_id
is the primary key for each category, category_name
is the descriptive name of the category, and parent_id
is a reference to the category_id
of the parent category. A category with no parent (a root node) would have NULL
as the value of parent_id
.
Step 2: Inserting Data
Here’s how you might insert some data into the categories
table:
INSERT INTO categories (category_name, parent_id) VALUES ('Electronics', NULL); -- Root node
INSERT INTO categories (category_name, parent_id) VALUES ('Laptops', 1); -- Child of Electronics
INSERT INTO categories (category_name, parent_id) VALUES ('Tablets', 1); -- Child of Electronics
INSERT INTO categories (category_name, parent_id) VALUES ('Gaming', 2); -- Child of Laptops
INSERT INTO categories (category_name, parent_id) VALUES ('Ultrabooks', 2); -- Child of Laptops
Step 3: Querying the Hierarchy
Querying an adjacency list model can be done using recursive common table expressions (CTEs) in PostgreSQL. This allows you to traverse the hierarchy and retrieve all levels of the tree.
Example: Retrieve the Full Hierarchy
WITH RECURSIVE category_tree AS (
SELECT category_id, category_name, parent_id
FROM categories
WHERE parent_id IS NULL
UNION ALL
SELECT c.category_id, c.category_name, c.parent_id
FROM categories c
INNER JOIN category_tree ct ON ct.category_id = c.parent_id
)
SELECT * FROM category_tree;
This recursive CTE starts with the root node (where parent_id
is NULL
) and recursively joins the categories
table to include all child nodes until the entire hierarchy is represented.
Example: Retrieve Specific Branch
If you want to retrieve just a specific branch of the tree, for example, all descendants of "Laptops":
WITH RECURSIVE category_tree AS (
SELECT category_id, category_name, parent_id
FROM categories
WHERE category_name = 'Laptops'
UNION ALL
SELECT c.category_id, c.category_name, c.parent_id
FROM categories c
INNER JOIN category_tree ct ON ct.category_id = c.parent_id
)
SELECT * FROM category_tree;
Conclusion
The adjacency model in PostgreSQL is quite powerful for managing hierarchical data, despite the potential complexity of querying deep hierarchies. By utilizing recursive CTEs, you can effectively manage and query hierarchical structures, though performance considerations should be taken into account when dealing with very large trees or deeply nested hierarchies.