← Все курсы · Курс SQL

Соединение таблицы самой с собой: менеджеры, пары и одна и та же таблица дважды

Майкл Носито · Обновлено в августе 2026 г. · Каждый запрос на этой странице был выполнен до его публикации.

Сотрудники и их менеджеры являются сотрудниками, поэтому оба живут в одной таблице. Чтобы отобразить имя рядом с именем менеджера, вам нужно соединить эту таблицу с самой собой, что первые несколько раз кажется неправильным и совершенно обычным.

Что вы делаете: дважды напишите таблицу с двумя псевдонимами и с этого момента обрабатывайте их как две отдельные таблицы. Для восьми сотрудников ниже внутренняя версия возвращает 6 строк, а ЛЕВАЯ версия — 8.

Краткая версия. Самостоятельное соединение — это обычное соединение. Единственная новая вещь заключается в том, что вы должны назвать две копии.

Стол

CREATE TABLE employees(emp_id INT, name TEXT, manager_id INT, dept TEXT, salary INT);
INSERT INTO employees VALUES
(1,'Alvarez',NULL,'Exec',120000),
(2,'Brennan',1,'Sales',72000),
(3,'Cho',1,'Sales',68000),
(4,'Diaz',2,'Sales',54000),
(5,'Ellis',2,'Sales',51000),
(6,'Fowler',3,'Support',49000),
(7,'Grant',NULL,'Support',47000),
(8,'Hale',3,'Support',45000);

manager_id указывает на emp_id в той же таблице. У Альвареса нет менеджера, как и у Гранта, и это имеет значение.

Запрос

SELECT e.name AS employee, m.name AS manager
FROM employees e
LEFT JOIN employees m ON m.emp_id = e.manager_id
ORDER BY e.emp_id;
сотрудникменеджер
АльваресNULL
БреннанАльварес
ДаватьАльварес
ДиасБреннан
ЭллисБреннан
ФаулерДавать
ГрантNULL
ХейлДавать

Прочитайте предложение соединения как предложение: копия менеджера emp_id равен копии сотрудника manager_id. Неправильный вариант — это самая распространенная ошибка самосоединения, и она дает результат, который выглядит нормально, пока вы не заметите, что иерархия перевернута.

Внутренний или ЛЕВЫЙ: 6 рядов против 8.

SELECT COUNT(*) FROM employees e JOIN employees m ON m.emp_id = e.manager_id;
-- 6

SELECT COUNT(*) FROM employees e LEFT JOIN employees m ON m.emp_id = e.manager_id;
-- 8

Внутреннее объединение молча теряет Альвареса и Гранта, поскольку ни у одного из них нет подходящей строки менеджера. В отчете о численности это ошибка двух человек из восьми, и она невидима: результат представляет собой совершенно нормальный список.

Правило обобщает. Любое самостоятельное присоединение к иерархии теряет ее вершину, а любое самостоятельное присоединение к иерархии теряет ее нижнюю часть. Решите, какой конец вы готовы отбросить, и если ответ ни тот, ни другой, используйте LEFT JOIN.

Грант - интересный ряд. У Альвареса нет менеджера, потому что они управляют компанией. У Гранта нет менеджера, потому что никто не определяет поле. Оба возвращают NULL, и запрос не может отличить их друг от друга. Это результат оценки качества данных, и он проявляется только тогда, когда кто-то присоединяет таблицу к самой себе.

Поиск пар в одной таблице

Другое основное применение: строки, которые что-то разделяют. Коллеги в одном отделе, заказы от одного и того же клиента в один и тот же день, дублирующиеся записи.

SELECT a.name, b.name, a.dept
FROM employees a
JOIN employees b ON b.dept = a.dept
WHERE a.emp_id < b.emp_id;

тот WHERE линия выполняет две задачи, и обе они необходимы. Без него каждый человек сопоставляется сам с собой, и каждая подлинная пара появляется дважды в обоих порядках. С a.emp_id < b.emp_id, каждая пара возвращается ровно один раз и не содержит пар строк сама с собой.

В продаже есть Бреннан, Чо, Диас и Эллис, что дает 6 пар. В поддержке есть Фаулер, Грант и Хейл, что дает 3. У Исполнительный директор есть один человек, а он не дает ни одного. Девять строк, а арифметика — проверка: н человек в отделе производят н(n-1)/2 пар.

Еще три формы, которые стоит знать

ВопросФорма
Кто зарабатывает больше своего менеджераПрисоединяйтесь сами, тогда WHERE e.salary > m.salary
Два уровня вверхПрисоединяйтесь к таблице три раза: сотрудник, менеджер, менеджер менеджера.
Вся цепочка, любая глубинаРекурсивный CTE, WITH RECURSIVE

По этим данным, Бреннан зарабатывает 72 000, а их менеджер Альварес — 120 000, так что никто не зарабатывает больше своего менеджера. Измените одно число, и запрос найдет его, что делает его полезным аудитом, а не головоломкой.

Три уровня — это практический предел для повторных объединений. Помимо этого или когда глубина меняется, вам нужна рекурсия, и это другая страница.

Ошибки в том порядке, в котором они происходят

  1. Никаких псевдонимов. База данных не может разрешить emp_id и вызывает неоднозначную ошибку столбца. Этот громкий, что делает его лучшим из пяти.
  2. Условие соединения изменилось. Никакой ошибки. Иерархия получается перевернутой.
  3. Внутреннее объединение образует иерархию. Никакой ошибки. Верхушка дерева исчезает.
  4. Никакого неравенства в парном запросе. Каждая пара дважды, плюс совпадения, поэтому считается двойной.
  5. Повсюду однобуквенные псевдонимы. Законно и нечитабельно через шесть месяцев. Использовать emp и mgr скорее, чем a и b когда две копии означают разные вещи.

Как применить это в своей работе

  1. Найдите в базе данных таблицу, которая указывает на себя: идентификатор менеджера, родительскую категорию, идентификатор заменяющей этой записи. Это встречается чаще, чем люди ожидают.
  2. Сначала напишите версию LEFT JOIN, посчитайте NULL и спросите, является ли каждый из них настоящей вершиной дерева или отсутствующим значением.
  3. Каждый раз сравнивайте внутренний и ЛЕВЫЙ счетчики. Разница заключается в количестве строк, которые внутренняя версия могла бы скрыть.
  4. Назовите свои псевдонимы по роли, а не по алфавиту.
  5. Прежде чем поверить в любой парный запрос, проверьте счетчик на соответствие н(n-1)/2.

Единственная привычка, которую нужно сохранить

Произнесите вслух предложение соединения как предложение о ролях: идентификатор строки менеджера равен идентификатору менеджера строки сотрудника. Самосоединение не имеет естественных имен таблиц, на которые можно было бы опереться, поэтому предложение — единственное, что сохраняет прямое направление.

В какой таблице вашей базы данных есть столбец, указывающий на собственный ключ?

Каждый номер здесь был проведён до того, как был опубликован. Восемь сотрудников. Внутреннее соединение возвращает 6 строк, LEFT JOIN возвращает 8, а запрос пары отделов возвращает 9.
Самосоединение — это момент, когда псевдонимы перестают быть стилем и становятся запросом.

SQL для аналитиков — это 458 страниц, которые считывают запросы построчно в повседневных словах, поэтому ошибочный результат нужно где-то отслеживать, а не перепечатывать, пока он не станет выглядеть лучше.

SQL для аналитиков, 19 $ →
Пишите соединения, а не читайте о них.

Объяснение SQL JOIN охватывает четыре типа, почему объединение дублирует строки описывает, что происходит, когда ключ не уникален, и SQL-практикум дает вам один работоспособный запрос за раз.

Откройте набор SQL →