SELF JOIN SQL: соединение таблицы с самой собой
SELF JOIN SQL нужен, когда строки одной таблицы требуется сопоставить с другими строками этой же таблицы. Разберём алиасы, условие соединения и пример связи сотрудника с руководителем.
Обновлено · Команда SQL Arena
Что потренируете
- Соединять одну таблицу с самой собой через разные алиасы
- Сопоставлять сотрудника с руководителем по manager_id
- Понимать, когда достаточно INNER JOIN, а когда нужен LEFT JOIN
- Строить уникальные пары условием a.id < b.id
- Не путать алиасы в SELECT, ON и WHERE
Пример задачи в тренажёре
Так выглядит задача в SQL Arena: условие, редактор, результат и схема базы.
В employees поле manager_id указывает на id другого сотрудника из той же таблицы. Нужно вывести сотрудника, его непосредственного руководителя и зарплату сотрудника только для тех случаев, где зарплата сотрудника выше.
SELECT e.employee_name AS employee, m.employee_name AS manager, e.salary FROM employees e JOIN employees m ON e.manager_id = m.id WHERE e.salary > m.salary ORDER BY e.salary DESC, e.employee_name;
| # | employee | manager | salary |
|---|---|---|---|
| 1 | Quinn | Nora | 130000 |
| 2 | Nora | Maya | 125000 |
| 3 | Pia | Leo | 98000 |
В employees поле manager_id указывает на id другого сотрудника из той же таблицы. Нужно вывести сотрудника, его непосредственного руководителя и зарплату сотрудника только для тех случаев, где зарплата сотрудника выше.
SELECT e.employee_name AS employee, m.employee_name AS manager, e.salary FROM employees e JOIN employees m ON e.manager_id = m.id WHERE e.salary > m.salary ORDER BY e.salary DESC, e.employee_name;
Как работает SELF JOIN SQL на примере
Таблица employees появляется в запросе дважды, но физически это всё та же таблица. Алиас e означает строку сотрудника, а m — строку его руководителя. Без алиасов PostgreSQL не сможет однозначно понять, к какому экземпляру таблицы относится employee_name, salary или id, поэтому в self join алиасы — не косметика, а часть логики запроса.
Условие e.manager_id = m.id связывает подчинённого с его непосредственным руководителем. Для Leo значение manager_id равно 1, поэтому к его строке присоединяется Maya с id = 1. Используется обычный JOIN, то есть INNER JOIN: сотрудник без руководителя, например верхний менеджер с manager_id = NULL, в результат не попадёт. Если бы нужно было показать всех сотрудников и оставить руководителя пустым там, где его нет, потребовался бы LEFT JOIN.
После соединения WHERE e.salary > m.salary сравнивает две строки одной исходной таблицы уже в разных ролях. В примере условие выполняется для Quinn, Nora и Pia. ORDER BY e.salary DESC, e.employee_name делает порядок результата однозначным. Это важно и в учебной задаче, и в реальном отчёте: без сортировки СУБД не обязана возвращать строки в одном и том же порядке.
SELECT e.employee_name AS employee, m.employee_name AS manager, e.salary FROM employees e JOIN employees m ON e.manager_id = m.id WHERE e.salary > m.salary ORDER BY e.salary DESC, e.employee_name;
| employee | manager | salary |
|---|---|---|
| Quinn | Nora | 130000 |
| Nora | Maya | 125000 |
| Pia | Leo | 98000 |
Типичные ошибки в SELF JOIN SQL
Соединять id с id
Условие вроде e.id = m.id сопоставит строку только с самой собой. Для иерархии нужно соединять внешний ключ роли сотрудника с первичным ключом роли руководителя: e.manager_id = m.id.
Забывать, какую роль играет алиас
Если в WHERE случайно сравнить m.salary > e.salary, задача меняется на противоположную. Полезно заранее назвать роли коротко и последовательно: e для employee, m для manager.
Генерировать пары через a.id <> b.id
Для задачи про все пары это создаст зеркальные дубли: A–B и B–A. Когда порядок участников не важен, условие a.id < b.id оставляет каждую пару один раз и одновременно исключает пару строки с самой собой.
Задачи по теме в тренажёре
Трек «Подготовка к собеседованию»После примера с иерархией стоит потренировать ещё две формы self join. В задачах про уникальные пары «категория — поставщик» важна борьба с повторяющимися комбинациями, а в задаче про сотрудников с зарплатой выше руководителя — правильная работа с отношением «строка ссылается на строку». Более сложные варианты доходят до карты прямых подчинённых и подсчёта всех связей руководителя. Для системной подготовки можно продолжить в треке «Подготовка к собеседованию». В SQL Arena доступно 1 192 задачи, а решения проверяются и на скрытых данных, поэтому запрос должен работать не только на видимых строках примера.
- EasyбесплатноУникальные пары «категория — поставщик»postgresql
- MediumбесплатноУникальные пары «категория — поставщик» в среднем ценовом сегментеpostgresql
- EasyбесплатноСотрудники с зарплатой выше, чем у руководителяpostgresqlmysqlclickhouse
- EasyбесплатноСуммарный баланс по клиентамpostgresqlmysqlclickhouse
- MediumPremiumТоп-2 пары «производитель — препарат»postgresqlmysql
- HardPremiumКомбинации пиццы с тремя топпингамиpostgresqlmysqlclickhouse
- ExpertPremiumОбщее число подчинённых у каждого руководителяpostgresql
- MediumPremiumКарта прямых подчинённыхpostgresql
Справочник по теме
Подробные статьи с синтаксисом и примерами в справочнике SQL Arena.
Частые вопросы
Что такое SELF JOIN SQL?
SELF JOIN — это соединение таблицы с самой собой. Одна и та же таблица участвует в запросе несколько раз под разными алиасами, чтобы строки могли играть разные логические роли.
Как сделать SELF JOIN в SQL?
Нужно указать одну таблицу дважды, дать каждому экземпляру свой алиас и задать условие JOIN между ними. Например, employee.manager_id можно сопоставить с manager.id в той же таблице сотрудников.
Зачем нужны алиасы в SELF JOIN?
Алиасы позволяют различать два логических экземпляра одной таблицы. Без них ссылки на одинаковые названия колонок становятся неоднозначными, а саму логику соединения трудно выразить корректно.
Чем SELF JOIN отличается от обычного JOIN?
Механизм соединения тот же: используются INNER JOIN, LEFT JOIN и условия ON. Отличие только в том, что при SELF JOIN обе стороны соединения ссылаются на одну физическую таблицу.
Попрактикуйтесь с SELF JOIN SQL
Откройте SQL Arena и решите несколько задач подряд: от простой связи сотрудник–руководитель до уникальных пар. Бесплатно доступны 292 задачи на PostgreSQL, MySQL, ClickHouse и BigQuery без привязки карты.
Практиковать SELF JOIN