MySQL Self Join

A self join lets you join a table to itself, treating it as two logical copies, so you can compare or relate rows within the same dataset.

Understanding the Self Join

A self join isn't a special SQL keyword — it's a regular INNER JOIN or LEFT JOIN where both sides of the join refer to the same table. Because a table can't be listed twice under its own name in a single query, you give it two different aliases so MySQL can tell which occurrence of a column you mean. Once aliased, the two references behave like independent tables that happen to share the same underlying rows.

When You Need One

Self joins show up whenever rows in a table relate to other rows in that same table. The classic example is an employees table where each row stores a manager_id that points to another employee's id. To print an employee alongside their manager's name, you need to look up a second row in the same table — exactly what a self join does.

  • Modeling hierarchies, such as employees who report to managers who are themselves employees
  • Comparing rows against each other, such as products that share the same price
  • Detecting duplicate records that differ only by primary key
  • Finding relationships between rows, such as consecutive orders placed by the same customer

List Each Employee With Their Manager's Name

SELECT e.name AS employee_name, m.name AS manager_name
FROM employees e
JOIN employees m ON e.manager_id = m.employee_id;

Notice that the table name employees appears twice, once aliased as e for the employee row and once as m for the manager row. Every column reference after that point must be prefixed with e. or m. so MySQL knows which occurrence you mean — without the aliases, the query would be ambiguous and fail to parse.

Find Employees Who Earn More Than Their Manager

SELECT e.name AS employee_name, e.salary, m.name AS manager_name, m.salary AS manager_salary
FROM employees e
JOIN employees m ON e.manager_id = m.employee_id
WHERE e.salary > m.salary;
employee_idnamemanager_id
1AliceNULL
2Bob1
3Carla1
4Dev2

Find Products That Share the Same Price

SELECT p1.product_name AS product_a, p2.product_name AS product_b, p1.price
FROM products p1
JOIN products p2 ON p1.price = p2.price AND p1.product_id < p2.product_id;
Note: Always give both aliases meaningful names, like e and m for employee/manager, rather than generic a and b — it makes the join condition self-documenting when you revisit the query later.
Note: Self joins compare a table against itself, so the effective work MySQL considers grows with the square of the table size before filtering. On very large tables, make sure the join column is indexed or you'll see slow full scans.

Exercise: MySQL Self Join

What is a self join?