N052-H3 Tier 4 · Advanced · hard hr · Helix Systems

Return every qualifying depth level and its employee count

Part of Recursive CTEs in SQL

The problem

Helix Systems' workforce analytics team wants to identify which depth levels in the organizational hierarchy carry significant headcount — depth levels with more than 5 employees.

Write a query to return every qualifying depth level and its employee count.

Assumptions:

  • The CEO has a missing manager_id and sits at depth 1. Employees one step below the CEO sit at depth 2, and so on.
  • The headcount at a depth level is the number of employees whose computed depth equals that level.
  • Only depth levels whose headcount is strictly greater than 5 should appear in the result.

Output:

  • One row per qualifying depth level, with columns depth and employee_count.
Schema · hr 4 tables
departments
id integer
name text
location text
budget numeric
salaries
id integer
employee_id integer
amount numeric
effective_date date
end_date? date
employees
id integer
name text
email text
department_id integer
manager_id? integer
hire_date date
title text
is_active boolean
job_history
id integer
employee_id integer
title text
department_id integer
start_date date
end_date? date

Run previews · Check grades

Write a query, then run it to see results here.

Worked solution Try it yourself first
Solution query
WITH RECURSIVE
  org AS (
    SELECT
      id,
      1 AS depth
    FROM
      employees
    WHERE
      manager_id IS NULL
    UNION ALL
    SELECT
      e.id,
      o.depth + 1
    FROM
      employees e
      JOIN org o ON e.manager_id = o.id
  ),
  level_counts AS (
    SELECT
      depth,
      COUNT(id) AS employee_count
    FROM
      org
    GROUP BY
      depth
  )
SELECT
  depth,
  employee_count
FROM
  level_counts
WHERE
  employee_count > 5

The shape

Three stages, two in a chained WITH clause and one in the main query. The first CTE walks the hierarchy and stamps each employee with their depth. The second CTE aggregates that flat result into one row per depth level. The main query then applies the > 5 threshold against the per-level count.

Clause by clause

  • The recursive CTE computes per-employee depth:
WITH RECURSIVE org AS (
    SELECT id, 1 AS depth
    FROM employees
    WHERE manager_id IS NULL
    UNION ALL
    SELECT e.id, o.depth + 1
    FROM employees e
    JOIN org o ON e.manager_id = o.id
)

Same top-down walk as the unbounded hierarchy traversal: anchor on the CEO at depth 1, recurse downward by matching each employee's manager_id to a row already in org, stamp each pass with one more than the source depth.

  • The chained CTE aggregates the recursion's output by level:
level_counts AS (
    SELECT depth, COUNT(id) AS employee_count
    FROM org
    GROUP BY depth
)

The second CTE reads org and collapses it into one row per depth value, with COUNT(id) returning the headcount at that level. Depth 1 shows 1, depth 2 shows 9, depth 3 shows 19, depth 4 shows 31.

  • The main query thresholds the per-level counts:
SELECT depth, employee_count
FROM level_counts
WHERE employee_count > 5

The filter employee_count > 5 runs against the named aggregate column. Depth 1 falls below the threshold and drops out; depths 2, 3, and 4 survive.

Why three stages and not two

The aggregation cannot live inside the recursive member — an aggregate would collapse rows the next pass needs to join against, and the recursion would break. The threshold cannot live in the level_counts CTE either, because that CTE's WHERE runs over the pre-aggregation rows in org, not over the aggregate employee_count. Each layer has one job. The recursion produces per-employee depth, the chained CTE produces per-level counts, and the main query applies the cutoff against the aggregate column. The three-stage shape is the standard way to layer "recurse, then aggregate, then threshold."

The trap

The threshold runs on the aggregate, not on individual employees. WHERE employee_count > 5 in the main query is comparing against the named column produced by COUNT(id) in the chained CTE. The named aggregate only exists once level_counts finishes computing; pushing the same filter into level_counts's WHERE would not work, because that WHERE runs over the pre-aggregation rows in org, where employee_count is not yet a column. The filter has to sit downstream of the aggregation, which is what the three-stage layering makes structurally explicit.

You practiced chaining a WITH RECURSIVE traversal into a follow-up CTE — recurse first to compute per-record depth, aggregate by depth in a second layer, then threshold-check in the main query.

How you actually get good at SQL

Reading explains SQL. Writing it, over and over with instant feedback, is what makes you fluent.

That's the whole SQLMaxx loop: 600+ real problems, instant AI feedback, mastery you can actually see, and spaced review that won't let you forget.

A stack of SQL practice problem cards, the top card showing an employees table.
615 problems · 66 concepts

Real problems. Not toy examples.

615 hand-built problems spanning all 66 concepts, from basic SELECTs to window functions, built on real schemas and real business questions, the kind you'll actually get asked on the job. Enough reps to make SQL automatic.

A retro computer showing a SQL query marked correct with a green checkmark.
Instant AI feedback

Write a query. Know if it's right in one second.

No copying an answer and hoping it clicked. The AI grader checks your real query against real data, catches exactly what's wrong, and explains the fix in plain English, like a senior analyst reading over your shoulder on every problem.

A circular mastery progress dial filling from blue to green, the SQLMaxx diamond at its center.
Mastery tracking

Stop guessing whether you actually know it.

SQLMaxx tracks every concept and shows you what you've mastered and what's still shaky. Your skills fill in one concept at a time, so 'I think I get joins' becomes something you can prove.

A SQL query editor circled by a blue return arrow with a clock, scheduled to come back for review.
Spaced review

Learn it once. Keep it for good.

Most of what you learn this week fades by next week. So when a concept comes due for review, SQLMaxx hands you a fresh problem to solve from a blank editor, not a flashcard to re-read. A research-backed spaced-repetition algorithm (FSRS) times each return for right before you'd forget, so your SQL is still there months later, when the interview or the job actually needs it.

Practice, feedback, mastery, review. That's the loop that turns reading into real skill.

Start free

No account, no credit card. Start solving in under a minute.