Scenario: Helix Systems' HR audit team is reviewing every salary record on file for employees in the Engineering department.
Task: Write a query to return each qualifying employee_id and their recorded salary amount.
Assumptions:
- An employee can have multiple salary records.
- The result covers only salary records belonging to employees whose department
nameis'Engineering'.
Output:
- One row per salary record belonging to an Engineering employee.
- Columns in this order:
employee_id,salary.
Schema · hr 4 tables
Run previews · Check grades
Write a query, then run it to see results here.
Worked solution Try it yourself first
WITH
engineering_employees AS (
SELECT
e.id AS employee_id
FROM
employees e
JOIN departments d ON e.department_id = d.id
WHERE
d.name = 'Engineering'
)
SELECT
s.employee_id,
s.amount AS salary
FROM
salaries s
JOIN engineering_employees ee ON ee.employee_id = s.employee_id The shape
Two phases compose: identify the qualifying employees (those in Engineering), then pull every salary record belonging to that set. The CTE captures the qualification step; the main query reads salaries and joins to the CTE to keep only the qualifying employees' rows.
Clause by clause
- The CTE
engineering_employeesjoinsemployeestodepartmentson the department key and filters tod.name = 'Engineering'. The projection is justemployee_id— that is the only column the main query needs to identify qualifying rows. SELECT s.employee_id, s.amount AS salaryprojects the requested columns directly from the salary record.FROM salaries s JOIN engineering_employees ee ON ee.employee_id = s.employee_idreads every salary record and keeps only those whose employee appears in the CTE. The CTE is acting as a filter set.
Why this and not a three-way join in one step
Writing the whole query as SELECT s.employee_id, s.amount FROM salaries s JOIN employees e ON e.id = s.employee_id JOIN departments d ON d.id = e.department_id WHERE d.name = 'Engineering' produces the same rows. The CTE shape buys readability and reuse: the "who counts as an Engineering employee" rule is named in one place, and if the main query needed to reference that set a second time, the name is already there. The structural choice the problem is practicing is the separation of the qualification logic from the outer pull.
The trap
An employee can have multiple salary records. The output here is one row per salary record, not one row per employee — so the same employee_id appears in the result for every salary record they have. If a downstream consumer needs one row per employee, the salary records would have to be aggregated first.
You practiced isolating the qualifying employees in an early CTE before pulling their salary records — a shape that keeps the qualification logic separate from the outer lookup.