Итак, давайте разберем необычные виды join, про которые не так часто вспоминают, но они по своему прекрасны. Погнали.
💻 SELF JOIN — соединение таблицы с самой собой
SELF JOIN используется, когда нам нужно сравнить строки внутри одной и той же таблицы.
SELECT e1.name AS employee, e2.name AS manager
FROM employees e1
JOIN employees e2 ON e1.manager_id = e2.id;
Где полезен:
➖Связи типа «сотрудник – менеджер»
➖Поиск пар с определённым соотношением
➖Сравнение записей между собой (например, временных интервалов)
Обратить внимание:
➖ Обязательно используйте алиасы (e1, e2) — иначе SQL не поймёт, откуда брать данные.
➖ Производительность при больших таблицах может быть тяжёлой без индексов.
💻 CROSS JOIN — декартово произведение
Каждая строка из первой таблицы соединяется со всеми строками второй.
SELECT c.color, s.size
FROM colors c
CROSS JOIN sizes s;
Где полезен:
➖ Генерация всех возможных комбинаций (цвет + размер, дата + товар и т.д.)
➖ Математические переборы (в BI/аналитике)
Пример:
Таблица colors:
red
blue
Таблица sizes:
S
M
L
Результат:
color size
red S
red M
red L
blue S
blue M
blue L
Обратить внимание:
➖ Растёт в геометрической прогрессии — при 100 строках в каждой таблице будет 10 000 строк в результате (100×100 = 10 000 строк)!
➖ Обычно требует явной фильтрации после соединения.
💻 NATURAL JOIN — соединение по совпадающим колонкам
Автоматически соединяет таблицы по колонкам с одинаковыми именами и типами.
SELECT *
FROM orders
NATURAL JOIN customers;
Где полезен:
➖ Быстрые выборки, когда точно знаешь схему таблиц
➖ Временные аналитические задачи или прототипирование
Обратить внимание:
➖ SQL сам решает, по каким колонкам соединять! Если колонок с одинаковыми именами много, можно получить непредсказуемый результат.
➖ Лучше не использовать в проде без явного указания колонок (ON), особенно если схему может кто-то изменить, потому что если структура изменится, все сломается.
💻 ANTI JOIN — найти то, чего нет
Ищем строки в первой таблице, у которых нет пары во второй.
На SQL делается через:
SELECT c.id
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id
WHERE o.id IS NULL;
ИЛИ:
SELECT c.id
FROM customers c
WHERE NOT EXISTS (
SELECT 1 FROM orders o WHERE o.customer_id = c.id
);
Где полезен:
➖ Найти клиентов без заказов
➖ Найти товары без продаж
➖ Обнаружение "провалов" в связях
Обратить внимание:
➖ Вариант с NOT EXISTS работает быстрее при наличии индекса
➖ Убедитесь, что NULL действительно означает отсутствие связи, а не ошибку в данных
💻 SEMI JOIN — проверка на наличие
Найти строки из одной таблицы, у которых есть хотя бы одна пара в другой таблице, но не вытаскивать её. Забавно, но его синтаксис это JOIN без JOIN:
SELECT c.id
FROM customers c
WHERE EXISTS (
SELECT 1 FROM orders o WHERE o.customer_id = c.id
);
В отличие от INNER JOIN, мы не получаем orders.* — только customers.
Где полезен:
➖ Проверка: есть ли связи?
➖ Ускорение выборок, когда нужны только факты "да/нет"
Обратить внимание:
➖ Не получится использовать данные из второй таблицы (orders) в SELECT — она просто фильтрует
➖ Неявный тип соединения, часто путают с INNER JOIN
➖ Не вытаскивает данные из второй таблицы.
❗️ ANTI JOIN и SEMI JOIN — неофициальные типы (в ANSI SQL их нет), реализуются через LEFT JOIN + WHERE, EXISTS и т.п.
💻 Итого:
➖ SELF — Сравнивает записи одной таблицы
➖ CROSS — Сравнивает все на все, юзается для генерации комбинаций
➖ NATURAL — Сравнивает по одинаковым колонкам, используем при уверенности неизменности структуры таблиц или с ON
➖ ANTI — Выбирает всё, что не связано, используем для поиска отсутствий
➖ SEMI — Выбирает всё, что связано, пишется без оператора JOIN
Поддержка:
➖ SELF, CROSS, NATURAL — есть в большинстве СУБД (PostgreSQL, MySQL, Oracle, MS SQL)
➖ SEMI JOIN, ANTI JOIN — не имеют отдельного синтаксиса, реализуются через EXISTS / NOT EXISTS / LEFT JOIN + IS NULL
➖ В PostgreSQL и Oracle EXISTS работает особенно эффективно благодаря индексам.
#Join #SQL
📱 Подписаться на канал
📱Мы в VK
💻 Курс автора по SQL DDL
