Knowledge Guide
HomeDatabasesSQL Practice Problems

medium Departments with High Earning Employees

The problem

Given an Employee table with id, name, department, and salary, find every department that has at least two employees who earn more than that department's own average salary. Return the qualifying departments ordered by department name.

The phrase that carries all the weight is "more than that department's own average." The threshold is not a single global number — it is recomputed per department. An employee is a "high earner" only relative to the colleagues sitting in the same department, and a department qualifies only when two or more of its members clear their local bar.

The example data

We will trace the whole solution on this concrete table, so it helps to name the rows up front. Three departments, ten employees:

idnamedepartmentsalary
101JohnA100
102DanA120
103JamesA110
104AmyB100
105AnneB130
106RonB115
107BobB125
108KimC90
109LeeC95
110SamC100

Note the three salaries in department A specifically: John 100, Dan 120, James 110. We will need all three again in a moment, and the fact that James earns 110 turns out to be the whole point.

diagram
diagram

Worked trace, department by department

Compute each department's average, then count how many of its members strictly exceed it.

Department A — avg = (100 + 120 + 110) / 3 = 110

Department A has 1 high earner. Not enough.

Department B — avg = (100 + 130 + 115 + 125) / 4 = 117.5

Department B has 2 high earners. It qualifies.

Department C — avg = (90 + 95 + 100) / 3 = 95

Department C has 1 high earner. Not enough.

Only department B clears the bar twice, so the answer is B.

Why a naive shortcut is wrong

A tempting simplification is to skip the per-department averages and compare every salary against one global average across the whole company. Let us actually run that wrong query on this data and watch it fail.

The global average over all ten salaries is

(100 + 120 + 110 + 100 + 130 + 115 + 125 + 90 + 95 + 100) / 10 = 1085 / 10 = 108.5

Now count, in each department, how many salaries exceed 108.5:

So the global-average query returns {A, B} — it reports A as well. But the correct answer is {B} alone: against A's own average of 110, only Dan clears the bar, so A has just one genuine high earner. The naive query produces a false positive on A.

The reason is structural, not accidental. James earns 110 — above the company-wide 108.5 but below his own department's 110 — so a global threshold counts him while a per-department threshold correctly does not. That single employee flips A from "1 high earner" to "2," which is exactly the boundary the problem cares about. The lesson: when the spec says "above the department's average," the average must be recomputed inside each group; substituting a single global number is not an approximation, it changes the result set.

The query

The standard approach is a self-join: pair each employee with every colleague in the same department, average those colleagues' salaries to get the department average, and keep the employee only when their salary strictly exceeds it. Then count survivors per department and keep departments with two or more.

SELECT department
FROM (
    SELECT department, COUNT(*) AS high_earners
    FROM (
        SELECT e.id, e.name, e.department, e.salary,
               AVG(e2.salary) AS avg_salary
        FROM Employee e
        JOIN Employee e2 ON e.department = e2.department
        GROUP BY e.id, e.name, e.department, e.salary
        HAVING e.salary > AVG(e2.salary)
    ) AS high_earners_per_dept
    GROUP BY department
    HAVING COUNT(*) >= 2
) AS result
ORDER BY department;

An equivalent and often clearer formulation uses a window function: AVG(salary) OVER (PARTITION BY department) computes the per-department average alongside each row without a self-join, after which you filter and count the same way.

Source

Problem and example data adapted from the LeetCode-style exercise "Departments with High Earning Employees" (Medium). Salary figures, per-department averages (A = 110, B = 117.50, C = 95.00), the global average (108.5), and the expected output (department B) were re-derived and verified directly from the example table in this lesson.

🤖 Don't fully get this? Learn it with Claude

Stuck on Departments with High Earning Employees? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🪜 Hint ladder (no spoilers)

Progressively stronger hints — you still solve it.

I'm working on the problem **Departments with High Earning Employees** (Databases). Give me a HINT LADDER: start with the tiniest nudge, then wait. Only reveal the next, stronger hint when I ask. Do NOT show the full solution unless I type 'show solution'. Keep me doing the thinking. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🎨 Explain the approach visually

See the technique, not just code.

Explain the optimal approach to **Departments with High Earning Employees** with a VISUAL walkthrough: trace it on a small concrete example using ASCII art / a step-by-step diagram, narrate what changes each step, then give time & space complexity with a one-line derivation. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🔍 Review my solution

Catch bugs, edge cases, sub-optimality.

I'll paste my solution to **Departments with High Earning Employees**. Review it for correctness, missed edge cases, and time/space complexity, then coach me toward the optimal — don't just rewrite it. Ask me to paste my code now. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🔁 Drill the pattern

Lock in recognition with look-alikes.

Give me 2 problems that use the SAME underlying pattern as **Departments with High Earning Employees**. For each, let me attempt first, then review my answer and name the trigger signal that reveals the pattern. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.

📝 My notes