SQL Practice Logo

SQLPractice Online

Self Joins: Interview

Module: Joins & Relationships

What is a self join and when would you use it?

A self join is joining a table to itself using different aliases. Use it for hierarchical relationships (employee-manager), comparing rows within the same table, or finding relationships within the same entity. Common examples: organizational charts, social networks, product recommendations.

Why do you need different aliases in self joins?

Aliases distinguish between different instances of the same table. Without aliases, the database cannot determine which table instance you are referencing. For example, e1 represents employees and e2 represents managers in an employee-manager self join.

When should you use LEFT JOIN vs INNER JOIN in self joins?

Use LEFT JOIN when some records may not have a matching relationship (like CEO having no manager). Use INNER JOIN when all records must have a relationship. LEFT JOIN preserves all records from the left table, INNER JOIN only returns records with matches.

Write a query to show all employees with their managers, including employees who have no manager.

SELECT

e1.employee_name AS employee,

COALESCE(e2.employee_name, 'No Manager') AS manager

FROM employees e1

LEFT JOIN employees e2 ON e1.manager_id = e2.employee_id

ORDER BY e1.employee_name;

LEFT JOIN preserves all employees. COALESCE handles NULL managers (CEO/top-level employees).

Find employees who earn more than their manager.

SELECT

e1.employee_name AS employee,

e1.salary AS employee_salary,

e2.employee_name AS manager,

e2.salary AS manager_salary

FROM employees e1

INNER JOIN employees e2 ON e1.manager_id = e2.employee_id

WHERE e1.salary > e2.salary

ORDER BY (e1.salary - e2.salary) DESC;

INNER JOIN excludes employees without managers. WHERE compares salaries between employee and manager.

Show the organizational hierarchy with employee levels (CEO = level 1, direct reports = level 2, etc.).

-- Using recursive CTE for multi-level hierarchy

WITH RECURSIVE employee_hierarchy AS (

-- Base case: CEO (no manager)

SELECT employee_id, employee_name, manager_id, 1 as level

FROM employees

WHERE manager_id IS NULL

UNION ALL

-- Recursive case: employees with managers

SELECT e.employee_id, e.employee_name, e.manager_id, eh.level + 1

FROM employees e

INNER JOIN employee_hierarchy eh ON e.manager_id = eh.employee_id

)

SELECT employee_name, level

FROM employee_hierarchy