Helix Systems' org-design team wants to identify employees who are managed within their own department — that is, employees whose direct manager is also in the same department.
Write a query to return the employee name and manager name for every such employee.
Assumptions:
- The
employeestable contains every active and former employee at Helix Systems. - The match is on the same
department_idfor both alias instances —e.department_idmust equalm.department_id. - Employees with no manager are excluded.
Output:
- One row per qualifying employee, with columns
employee_nameandmanager_name.
Schema · hr 4 tables
Run previews · Check grades
Write a query, then run it to see results here.
Worked solution Try it yourself first
SELECT
e.name AS employee_name,
m.name AS manager_name
FROM
employees e
JOIN employees m ON e.manager_id = m.id
WHERE
e.department_id = m.department_id The shape
The question pairs two rows that share a column value, so the predicate names that column on both aliases: e.department_id = m.department_id. The manager_id = id link gives you the employee-manager pair; the department equality narrows that pair to within-department reporting.
Clause by clause
SELECT e.name AS employee_name, m.name AS manager_namereturns the employee name and manager name from the two aliased instances.FROM employees ereadsemployeesin the employee role.JOIN employees m ON e.manager_id = m.idpairs each employee with their direct manager. This is the link that builds the reporting relationship.WHERE e.department_id = m.department_idkeeps only the pairs where both sides sit in the same department. Marcus Reid (Engineering) reporting to Sarah Chen (Engineering, as the CEO heading that department in the data) survives; an employee in Engineering reporting to a manager in Sales would not.
Why this and not WHERE e.department_id = 1 AND m.department_id = 1
The two filters do different things. e.department_id = 1 AND m.department_id = 1 returns within-department reporting for Engineering only — a hard-coded department. e.department_id = m.department_id returns within-department reporting for every department, because the equality holds whenever both sides match, whatever the value happens to be. The prompt asks for the general case, so the predicate compares the two aliases instead of pinning either to a literal.
The trap
A predicate that compares two columns on the same row reads almost identically to a predicate that compares two literals against one column, but they answer entirely different questions. e.department_id = m.department_id is a row-relational filter (true when the two participants share the value); e.department_id = 1 is a row-absolute filter (true when this row has this exact value). Self-joins make the first form natural because the two aliases give two sides to compare. Use the column-to-column form whenever the question is about a shared attribute rather than a specific value.
You practiced a self-join condition that compares a column on both alias instances. The recurring shape: when the question relates two rows on a shared attribute (same department, same date, same status), the join condition or WHERE clause names that attribute on both aliases.