SELF JOIN - это не отдельное ключевое слово. На самом деле это обычное соединение (чаще всего INNER JOIN или LEFT JOIN), при котором таблица соединяется с самой собой. Это полезно для запросов к иерархическим данным или для сравнения строк внутри одной и той же таблицы.
Чтобы выполнить самосоединение, вы должны обращаться к одной таблице так, словно это две разные таблицы. Для этого обязательно нужно использовать псевдонимы (aliases), чтобы дать каждому экземпляру таблицы уникальное имя. Без псевдонимов база данных не поймет, к какому экземпляру относится тот или иной столбец.
Визуализация (иерархия сотрудников):
Представьте таблицу employee, где у каждой строки есть поле manager_id, которое указывает на employee_id их начальника.
Таблица A (Сотрудники) Таблица B (Менеджеры)
+----+-------+---------+ +----+-------+
| id | имя | mgr_id | | id | имя |
+----+-------+---------+ +----+-------+
| 1 | Алиса | NULL | | 1 | Алиса |
| 2 | Боб | 1 | <-> | 1 | Алиса | (Начальник Боба - Алиса)
| 3 | Кэрол | 1 | <-> | 1 | Алиса | (Начальник Кэрол - Алиса)
+----+-------+---------+ +----+-------+
SELECT
e.name AS employee_name,
m.name AS manager_name
FROM
employee AS e
LEFT JOIN
employee AS m ON e.manager_id = m.id;
employee AS e: Первый экземпляр (представляет сотрудников).employee AS m: Второй экземпляр (представляет менеджеров).ON e.manager_id = m.id: Условие, которое их связывает.Предположим, мы хотим найти пары фильмов, у которых абсолютно одинаковая длительность (length). Мы можем соединить таблицу film саму с собой.
SELECT
f1.title AS film_1,
f2.title AS film_2,
f1.length
FROM
film AS f1
INNER JOIN
film AS f2 ON f1.length = f2.length
WHERE
f1.film_id <> f2.film_id -- Убеждаемся, что мы не сравниваем фильм сам с собой
LIMIT 10;
Условие f1.film_id <> f2.film_id критически важно. Без него каждый фильм совпал бы сам с собой (так как его длительность равна самой себе).
Если мы хотим увидеть, какие клиенты живут по одному адресу (на основе address_id в этом упрощенном примере):
SELECT
c1.first_name AS cust_1_first,
c1.last_name AS cust_1_last,
c2.first_name AS cust_2_first,
c2.last_name AS cust_2_last,
c1.address_id
FROM
customer AS c1
INNER JOIN
customer AS c2 ON c1.address_id = c2.address_id
WHERE
c1.customer_id < c2.customer_id; -- Используем '<' вместо '<>', чтобы избежать дубликатов пар (A-B и B-A)
ON для определения связей между строками (например, иерархия или общие атрибуты).WHERE, такие как id1 <> id2 или id1 < id2, чтобы избежать сопоставления строки самой с собой или повторения одних и тех же пар.