Self Join

RoadmapsSQL

Overview

A self join is a join where a table is joined to ITSELF. You write the same table name twice, giving each occurrence a different alias, then join on a relationship between rows in that table — typically a foreign key that points back to the same table's primary key. The classic example is the employees table, where manager_id references another row's id in the same table: SELECT e.name AS employee, m.name AS manager FROM employees e INNER JOIN employees m ON e.manager_id = m.id ORDER BY e.name; This pairs each employee with their manager. Sara (the CEO, manager_id = NULL) is excluded because INNER JOIN drops unmatched rows — she has no manager to match. Self joins are not a special syntax — they use the exact same JOIN you already know. The only difference is both sides of the join reference the same table, so aliases are mandatory to distinguish 'the employee row' from 'the manager row'. Mental model: imagine two COPIES of the same table side by side — one copy represents 'the child row', the other represents 'the parent row'. The ON clause links them.

Hierarchical data lives in a single table (employees → manager, categories → parent category, comments → parent comment). Self joins let you navigate one level of that hierarchy. They also let you compare rows within the same table — e.g., finding employees who earn more than their manager.

Where used: org chart and manager lookups, threaded comment trees, category → subcategory navigation, comparing rows in the same table

Why learn this

Query walkthrough

SELECT e.name AS employee, m.name AS manager
FROM employees e
INNER JOIN employees m ON e.manager_id = m.id
ORDER BY e.name;

Focus: Watch the employees table appear TWICE — alias 'e' is the employee copy, alias 'm' is the manager copy. The ON clause links each employee's manager_id to the manager's id. Sara vanishes because her NULL manager_id matches no id.

Common mistakes

Glossary

occurrence
A specific instance or time that something appears, like writing the same table name twice in a query.
mandatory
Required by a rule or law; something that must be done, like using an alias when joining a table to itself.
subordinates
People or items that are at a lower rank or level in a hierarchy, like employees reporting to a manager.

Recall questions

Understanding checks

What rows does this return? Pay attention to Sara.

Sara, NULL Tom, Sara Uma, Tom Victor, Tom Wendy, Sara Xavier, Wendy Yara, Wendy

LEFT JOIN keeps every employee, including Sara whose manager_id is NULL. Sara's manager column is NULL because she has no match. The other 6 employees are matched to their managers via manager_id = m.id.

Which employees earn more than their manager?

No rows are returned (empty result set).

Checking each employee against their manager: Tom(150000) vs Sara(200000) — no. Uma(120000) vs Tom(150000) — no. Victor(110000) vs Tom(150000) — no. Wendy(130000) vs Sara(200000) — no. Xavier(95000) vs Wendy(130000) — no. Yara(90000) vs Wendy(130000) — no. No employee earns more than their manager.

Practice tasks

Include the CEO in the results

This query uses INNER JOIN, so Sara (the CEO with no manager) is excluded. Change the join type so that Sara appears in the results with manager = NULL. Keep the ordering.

Challenge

Employees in the same department

Write a query that lists all pairs of employees who work in the same department. Show employee1 and employee2 names, and the department. Avoid duplicate pairs (ensure employee1 name < employee2 name). Order by department, then employee1.

Continue learning

Previous: INNER JOIN

Next: Recursive CTEs

Return to SQL Roadmap