Self join patterns in PostgreSQL - Time & Space Complexity
When we use a self join, we combine a table with itself to compare rows. Understanding how long this takes helps us know if the query will run fast or slow as data grows.
We want to find out how the work needed changes when the table gets bigger.
Analyze the time complexity of the following code snippet.
SELECT a.id, b.id
FROM employees a
JOIN employees b ON a.manager_id = b.id;
This query finds pairs of employees and their managers by joining the employees table to itself.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Comparing each row in the first table to rows in the second table to find matches.
- How many times: For each of the n rows, the database looks for matching rows in the same table, potentially checking many rows.
As the number of employees grows, the number of comparisons grows quickly because each row is checked against others.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 100 comparisons |
| 100 | About 10,000 comparisons |
| 1000 | About 1,000,000 comparisons |
Pattern observation: The work grows much faster than the number of rows; doubling rows roughly quadruples the work.
Time Complexity: O(n²)
This means if the table size doubles, the work needed to complete the join roughly quadruples.
[X] Wrong: "A self join only takes as long as a normal join, so it's always fast."
[OK] Correct: Because the table joins with itself, the number of comparisons can grow much faster, making the query slower as data grows.
Understanding how self joins scale helps you explain query performance clearly and shows you can think about how data size affects work done.
"What if we add an index on the manager_id column? How would the time complexity change?"
Practice
self join in PostgreSQL?Solution
Step 1: Understand the concept of self join
A self join is used when you want to compare rows within the same table by joining the table to itself.Step 2: Differentiate from other joins
Other joins combine different tables, but self join works on one table with aliases to distinguish instances.Final Answer:
To join a table to itself to compare rows within the same table -> Option AQuick Check:
Self join = join table to itself [OK]
- Confusing self join with joining two different tables
- Thinking self join creates a new table
- Assuming self join deletes duplicates
employees with aliases e1 and e2?Solution
Step 1: Identify correct alias usage
Using aliases e1 and e2 for the same table employees is necessary to distinguish instances.Step 2: Check join condition
The join condition e1.manager_id = e2.id correctly links employees to their managers.Final Answer:
SELECT * FROM employees e1 JOIN employees e2 ON e1.manager_id = e2.id; -> Option DQuick Check:
Use aliases and proper ON condition [OK]
- Not using aliases causing ambiguity
- Wrong join condition columns
- Using comma join without ON clause
employees(id, name, manager_id) with data:id | name | manager_id ---+-------+----------- 1 | Alice | NULL 2 | Bob | 1 3 | Carol | 1 4 | Dave | 2
What will be the output of this query?
SELECT e1.name AS employee, e2.name AS manager FROM employees e1 LEFT JOIN employees e2 ON e1.manager_id = e2.id ORDER BY e1.id;
Solution
Step 1: Understand the join logic
The LEFT JOIN matches each employee's manager_id to the manager's id, returning manager's name or null if none.Step 2: Map each employee to their manager
Alice has no manager (null), Bob and Carol have Alice as manager, Dave has Bob as manager.Final Answer:
[{"employee": "Alice", "manager": null}, {"employee": "Bob", "manager": "Alice"}, {"employee": "Carol", "manager": "Alice"}, {"employee": "Dave", "manager": "Bob"}] -> Option BQuick Check:
LEFT JOIN matches manager_id to id [OK]
- Confusing employee and manager columns
- Using INNER JOIN losing employees without managers
- Assuming manager_id is employee id
SELECT e1.name, e2.name FROM employees e1 JOIN employees e2 ON e1.manager_id = e2.manager_id WHERE e1.id != e2.id;
What is the main issue with this query?
Solution
Step 1: Analyze join condition
The join matches employees with the same manager_id, including reversed pairs.Step 2: Check WHERE clause effect
WHERE e1.id != e2.id avoids self-pairing but does not prevent duplicate pairs in reverse order.Final Answer:
It will return duplicate pairs in both orders (e.g., (Alice, Bob) and (Bob, Alice)) -> Option AQuick Check:
Self join can produce reversed duplicate pairs [OK]
- Assuming WHERE clause removes duplicates
- Thinking query causes syntax error
- Believing it returns only employees without managers
Solution
Step 1: Understand the requirement
Managers are employees whose id appears as manager_id for others.Step 2: Analyze each option
SELECT DISTINCT e1.name FROM employees e1 JOIN employees e2 ON e1.id = e2.manager_id; joins employees where e1.id = e2.manager_id, selecting distinct managers correctly.Final Answer:
SELECT DISTINCT e1.name FROM employees e1 JOIN employees e2 ON e1.id = e2.manager_id; -> Option CQuick Check:
Join on id = manager_id finds managers [OK]
- Using LEFT JOIN with IS NULL returns non-managers
- Joining on wrong columns (manager_id = id reversed)
- Filtering on manager_id IS NOT NULL returns employees with managers
Ready to prove it?
Pass the test and this pattern moves unknown
