Reviewed by Aditya Kumar · Last reviewed 2026-08-08
A self join treats one table as two logical tables so you can relate rows to other rows in the same table. For an employee list where each row stores its own manager's id, you join employees to…
This medium-level SQL question appears frequently in data engineering interviews at companies like Gartner. While less common, it tests deeper understanding that distinguishes strong candidates. Mastering the underlying concepts (join) will help you answer variations of this question confidently.
Break this problem into components. Identify the core trade-offs involved, then walk the interviewer through your reasoning step by step. Demonstrate awareness of edge cases and production considerations - this is what separates good answers from great ones. The expert answer includes a code example that demonstrates the implementation pattern.
A self join treats one table as two logical tables so you can relate rows to other rows in the same table. For an employee list where each row stores its own manager's id, you join employees to itself: once as the employee, once as the manager.
SELECT e.name AS employee_name,
m.name AS manager_name
FROM employees e
LEFT JOIN employees m
ON e.manager_id = m.id;
The alias is what makes this work: e and m are two independent cursors over the same physical table, so the optimizer treats them as separate inputs. Use a LEFT JOIN because the top of the hierarchy has a NULL manager_id. An INNER JOIN silently drops the CEO, and quietly losing rows is the single most common mistake on this question. If you want a friendlier output, wrap the result: COALESCE(m.name, 'No manager').
A self join only climbs one level. To walk an arbitrary-depth org chart you need a recursive CTE:
WITH RECURSIVE chain AS (
SELECT id, name, manager_id, 1 AS depth
FROM employees
WHERE manager_id IS NULL
UNION ALL
SELECT e.id, e.name, e.manager_id, c.depth + 1
FROM employees e
JOIN chain c ON e.manager_id = c.id
)
SELECT * FROM chain;
Index manager_id, since it is the join key and is usually unindexed on a table that was designed around id. Real org data also contains cycles from bad imports, and a recursive CTE on a cycle runs until it exhausts memory, so guard it with a depth cap.
In the interview, also mention that the same self-join pattern solves "find employees earning more than their manager" by adding WHERE e.salary > m.salary.
Red Flag: INNER JOIN excludes CEO. Pro-Move: 'LEFT JOIN; recursive CTE for org hierarchy reporting.'
Some links below are affiliate links. If you buy through them we may earn a small commission at no extra cost to you — it helps keep DataEngPrep free.
According to DataEngPrep.tech, this is one of the most frequently asked SQL interview questions, reported at 1 company. DataEngPrep.tech maintains an editor-reviewed database of 1,863 data engineering interview questions across 7 categories.