Recent chats
ASKGEEZ Q&A GUIDETechnology & devices

How do I compare records within the same table using a self-join?

Quick answer

Join the table to itself, giving each occurrence a different alias. Match the employee’s manager_id to the manager row’s employee_id. For example, employees AS e JOIN employees AS m ON e.manager_id = m.employee_id pairs the two rows. Select employee details from e and manager details from m, labeling the output columns so their roles are clear. [S1]

LET’S WORK THROUGH IT

The question, the details, the next step.

Question

I have one table of employees, and each employee record has a manager ID. How can I show an employee next to their manager without making a separate managers table?

Geez

Join the employees table to itself. Think of the two appearances as two roles: e is the employee being listed, and m is the manager being looked up. The ON condition pairs a row where e.manager_id matches another row’s m.employee_id. A self-join uses the same table as both inputs with separate aliases, and the ON expression specifies which row pairs to include. [S1]

Assume this illustrative schema, where manager_id stores the employee ID of the manager:

employees(employee_id, name, manager_id)

Here is a query that returns employee-manager pairs when the IDs match:

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

The schema and records below are invented for explanation; substitute your own table and column names.

Follow-up question

Can you show what the data and result would look like? I want to check which columns come from each alias.

Geez

Suppose the illustrative table contains these rows:

employee_id | name  | manager_id
1           | Amina | NULL
2           | Ben   | 1
3           | Chen  | 1

The query would produce these matched employee-manager pairs:

employee_id | employee_name | manager_id | manager_name
2           | Ben           | 1          | Amina
3           | Chen          | 1          | Amina

For Ben’s result, e refers to Ben’s row and m refers to Amina’s row: Ben’s manager_id is 1, and Amina’s employee_id is 1. The selected e columns describe the employee; the selected m columns describe the matching manager. Amina does not appear as an employee in this result because her manager_id is NULL, so it does not match an employee_id in the example. The sample is only a demonstration, not a claim about any real organization.

Follow-up question

Why use JOIN here? I want to include employees even when they do not have a manager ID.

Geez

The query shown uses JOIN to return employee-manager row pairs that satisfy the ON condition. It therefore demonstrates the matching case, but it does not include an employee row such as Amina’s when there is no matching manager ID. The ON expression determines which candidate row pairs are included. [S1]

To choose a different join type for a report that must retain employees without a matching manager, check the documentation for your specific database and join type. The source-backed example here uses JOIN for matched pairs; the appropriate query depends on the result you want and the database you use. In either version, keep the relationship condition clear: e.manager_id = m.employee_id.

Follow-up question

What should I check if the query gives duplicated employees or no manager names?

Geez

Start by checking the relationship the query assumes: an employee’s manager_id should match the manager row’s employee_id. Confirm that those are the intended ID columns and that the expected manager row is present. The example’s ON condition is specifically what pairs rows whose IDs match. [S1]

To inspect which rows are being paired, temporarily include both IDs in the output, as the query does with e.employee_id and m.employee_id. Also label columns from each alias separately, such as e.name AS employee_name and m.name AS manager_name, so you can distinguish the two roles. If the results still do not fit your data, check your actual table structure and database documentation; the illustrative schema cannot establish your system’s data rules.

A practical checklist

  • Identify the employee ID column and the column that stores the manager’s ID.

  • Give the two appearances of the table clear, different aliases, such as e and m.

  • Match e.manager_id to m.employee_id in the ON condition.

  • Select and label employee and manager fields separately to distinguish their roles.

  • Check the result you want and consult your database’s documentation if you need a different join type.

  • If results look unexpected, verify the ID columns and the rows being paired.

A few more useful answers

Why do the two table aliases need different names?

They distinguish the two roles played by the same table: the employee row and the manager row. Use the relevant alias before each column name, such as e.name or m.name. [S1]

Does this example include employees who have no matching manager row?

The example uses JOIN to show matched employee-manager pairs. For a different result, such as retaining employees without a match, check the documentation for your database and the join type you need.

Does this example tell me what my database columns are called?

No. employee_id, name, and manager_id are illustrative placeholders. Check your table definition and substitute its actual column names.

Sources

References used for this guide.

  1. [S1] SQLite SELECT: joining tables and ON constraints
    sqlite.org · Checked

YOUR QUESTION. YOUR DETAILS.

Let’s work through your situation.

Get a tailored answer or help with your next task. Starts at $1, with a quote before you pay.

Ask your own question
← Back to Geez at Work