CTEs & Window Functions SQL practice problemHardVerified answer

Organization Hierarchy With Subordinate Counts (Recursive CTE)

Return each employee with their full management chain using a recursive CTE.

  • Recursive CTE
  • CTEs
  • Joins
  • Subqueries
  • Aggregation

Interview brief

Understand the request

Org design analyst The org hierarchy report uses a recursive CTE to walk the management chain from each employee up to the top.

Build the org hierarchy with a recursive CTE. For each employee show their org_level (CEO = 1), the full management_path (CEO -> … -> employee), and total_subordinates (everyone in their reporting chain, direct + indirect). Return employee_id, first_name, last_name, org_level, management_path, total_subordinates — ordered by org_level, employee_id.

Return

  • Return employee_name, manager_name, and level (depth in hierarchy).

Constraints

  • Use a recursive WITH clause to traverse the self-referencing manager_id relationship.

Data you will use

Review the relevant tables before deciding how to join, filter, or aggregate them.

employees

  • employee_idINTEGER
  • first_nameVARCHAR(50)
  • last_nameVARCHAR(50)
  • manager_idINTEGER

Hints, when you need them

Open one clue at a time so you still do the reasoning.

Hint 1

Recursive CTE: anchor (CEO, level 1) UNION ALL the step that joins each employee to their manager row.

Hint 2

Build management_path by concatenating names as you descend.

Hint 3

Subtree count: a node's descendants are exactly the rows whose path STARTS WITH this node's path (LIKE path || '%'); subtract 1 to exclude self.

Verified SQL answer

Attempt the problem first, then compare structure and reasoning—not just syntax.

Reveal solution and explanation
WITH RECURSIVE org AS (SELECT employee_id, first_name, last_name, manager_id, 1 AS org_level, first_name || ' ' || last_name AS management_path FROM employees WHERE manager_id IS NULL UNION ALL SELECT e.employee_id, e.first_name, e.last_name, e.manager_id, o.org_level + 1, o.management_path || ' -> ' || e.first_name || ' ' || e.last_name FROM employees e INNER JOIN org o ON e.manager_id = o.employee_id), sub AS (SELECT a.employee_id, COUNT(b.employee_id) - 1 AS total_subordinates FROM org a LEFT JOIN org b ON b.management_path LIKE a.management_path || '%' GROUP BY a.employee_id) SELECT o.employee_id, o.first_name, o.last_name, o.org_level, o.management_path, s.total_subordinates FROM org o INNER JOIN sub s ON s.employee_id = o.employee_id ORDER BY o.org_level, o.employee_id;

Why this works

Recursive CTEs walk arbitrary-depth hierarchies. The path-prefix LIKE trick is a neat way to count an entire subtree without a second recursion. Note: on MySQL/SQL Server the `||` concatenation must become CONCAT/+.

Expected result

Use this output to verify values, aliases, ordering, and row count.

employee_idfirst_namelast_nameorg_levelmanagement_pathtotal_subordinates
1JenniferKing1Jennifer King14
2MichaelScott2Jennifer King -> Michael Scott5
3SarahJohnson2Jennifer King -> Sarah Johnson3
11PatriciaDavis2Jennifer King -> Patricia Davis1
13JessicaMoore2Jennifer King -> Jessica Moore1
4DavidMartinez3Jennifer King -> Michael Scott -> David Martinez0
5EmilyChen3Jennifer King -> Michael Scott -> Emily Chen0
6RobertWilliams3Jennifer King -> Michael Scott -> Robert Williams0
7LisaAnderson3Jennifer King -> Michael Scott -> Lisa Anderson0
8JamesTaylor3Jennifer King -> Sarah Johnson -> James Taylor0

Previewing 10 of 15 expected rows. Run the query in the editor to inspect the full result.

Learn the concepts behind this answer

Strengthen your understanding with these targeted learning topics: