JOIN в SQL: виды соединений таблиц и примеры запросов

Аналитика 6 мин чтения

JOIN в SQL соединяет строки двух таблиц по общему полю, например заказы и клиентов по номеру клиента. Основных видов четыре: INNER JOIN оставляет только совпадающие строки, LEFT JOIN — все строки левой таблицы, RIGHT JOIN — все строки правой, FULL JOIN — все строки обеих. Там, где пары не нашлось, в столбцах подставляется NULL.

4 видаосновных соединений: INNER, LEFT, RIGHT и FULL
ONусловие, по которому сравниваются строки двух таблиц
NULLзначение в столбцах, для которых не нашлось пары
LEFT JOINсамый частый вид соединения в аналитических запросах

Главное за 30 секунд

  • JOIN склеивает таблицы по ключу, чтобы в одном результате были, например, заказ и имя клиента.
  • INNER JOIN — только пары, которые есть в обеих таблицах.
  • LEFT JOIN — все строки левой таблицы, даже если справа пары нет; RIGHT JOIN — то же для правой.
  • FULL JOIN — все строки обеих таблиц; в MySQL его заменяют объединением LEFT и RIGHT JOIN через UNION.
  • Главные ошибки — дубли при связи «один ко многим» и фильтр в WHERE, который превращает LEFT JOIN в INNER.

Как работает JOIN на примере двух таблиц?

Возьмём две таблицы: клиентов и их заказы. У клиента Ольги заказов нет, а заказ 104 оформлен на клиента с номером 4, которого нет в таблице клиентов.

clients
idname
1Анна
2Борис
3Ольга
orders
idclient_idamount
10115 000
10212 500
10327 000
10441 200

Таблицы соединяются по условию clients.id = orders.client_id. От вида JOIN зависит, что произойдёт со строками без пары: с Ольгой и с заказом 104.

INNER JOIN — только совпадения

SELECT c.name, o.id AS order_id, o.amount
FROM clients c
INNER JOIN orders o ON c.id = o.client_id;

Результат — три строки: два заказа Анны и заказ Бориса. Ольга без заказов и заказ 104 без клиента в результат не попали. Слово INNER можно не писать: просто JOIN означает то же самое.

nameorder_idamount
Анна1015 000
Анна1022 500
Борис1037 000

LEFT JOIN — все строки левой таблицы

SELECT c.name, o.id AS order_id, o.amount
FROM clients c
LEFT JOIN orders o ON c.id = o.client_id;

Результат — четыре строки: к трём совпадениям добавилась Ольга, у которой в столбцах заказа стоит NULL. LEFT JOIN используют, когда важно не потерять ни одной строки основной таблицы, например всех клиентов при подсчёте их заказов.

nameorder_idamount
Анна1015 000
Анна1022 500
Борис1037 000
ОльгаNULLNULL
SELECT c.name, o.id AS order_id, o.amount
FROM clients c
RIGHT JOIN orders o ON c.id = o.client_id;

Результат — четыре строки: три совпадения и заказ 104, у которого имя клиента NULL. RIGHT JOIN встречается редко: тот же результат получают через LEFT JOIN, поменяв таблицы местами.

FULL JOIN — все строки обеих таблиц

SELECT c.name, o.id AS order_id, o.amount
FROM clients c
FULL JOIN orders o ON c.id = o.client_id;

Результат — пять строк: три совпадения, Ольга без заказов и заказ 104 без клиента. FULL JOIN помогает сверять два справочника и находить расхождения. В MySQL его нет — там объединяют результаты LEFT и RIGHT JOIN через UNION.

Чем отличаются виды JOIN?

ВидЧто попадает в результатСтрок в примере
INNER JOINТолько строки, у которых есть пара в обеих таблицах3
LEFT JOINВсе строки левой таблицы + пары из правой или NULL4
RIGHT JOINВсе строки правой таблицы + пары из левой или NULL4
FULL JOINВсе строки обеих таблиц5
CROSS JOINКаждая строка левой с каждой строкой правой, без условия3 × 4 = 12

Отдельно выделяют SELF JOIN — соединение таблицы с самой собой, например чтобы вывести сотрудника рядом с его руководителем из той же таблицы.

Соединяйте таблицы на реальных бизнес-кейсах

Курс «Обработка и анализ данных в SQL» от SF Education: 6 практических заданий и 2 бизнес-кейса за 1 месяц, JOIN, группировки и аналитические запросы.

Какие ошибки чаще всего делают с JOIN?

  • Дубли строк. Если у одного клиента несколько заказов, после JOIN клиент повторится столько раз, сколько у него заказов. Сумма по полю клиента после такого соединения окажется завышенной — сначала агрегируйте, потом соединяйте.
  • Фильтр в WHERE после LEFT JOIN. Условие WHERE o.amount > 1000 отбросит строки, где amount равен NULL, и LEFT JOIN фактически превратится в INNER. Условие для правой таблицы переносят в ON.
  • Соединение не по тому ключу. Если ключ неуникален в обеих таблицах, строки размножаются. Перед соединением проверьте уникальность ключа через COUNT и COUNT(DISTINCT).
  • Разные типы ключей. Номер клиента в одной таблице хранится числом, в другой — строкой: часть пар не найдётся. Приведите типы через CAST.

Как найти записи без пары?

Чтобы найти клиентов без заказов, используют LEFT JOIN и проверку на NULL в правой таблице:

SELECT c.id, c.name
FROM clients c
LEFT JOIN orders o ON c.id = o.client_id
WHERE o.id IS NULL;

В нашем примере запрос вернёт Ольгу. Так же ищут товары без продаж или платежи, которые не привязались к счёту.

Пример SQL-запроса с JOIN и группировкой

Запрос считает число заказов и сумму покупок по каждому клиенту, включая клиентов без заказов:

SELECT c.name,
       COUNT(o.id)              AS orders,
       COALESCE(SUM(o.amount), 0) AS total
FROM clients c
LEFT JOIN orders o ON c.id = o.client_id
GROUP BY c.name
ORDER BY total DESC;

COUNT(o.id) не считает NULL, поэтому у Ольги будет 0 заказов, а COALESCE заменит пустую сумму на ноль. Основы запросов — в статье что такое SQL.

Частые вопросы

Чем LEFT JOIN отличается от INNER JOIN?

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

JOIN и INNER JOIN — это одно и то же?

Да. Если написать просто JOIN без уточнения, база выполнит INNER JOIN. Слово INNER добавляют для читаемости, чтобы сразу было видно вид соединения.

Почему после JOIN строк стало больше, чем было?

Так происходит при связи «один ко многим»: если у клиента три заказа, его строка повторится три раза. Это нормальное поведение JOIN. Если нужна одна строка на клиента, сначала сгруппируйте заказы в подзапросе, а потом соединяйте.

Как найти строки, которых нет во второй таблице?

Используйте LEFT JOIN и условие WHERE правая_таблица.id IS NULL. Запрос вернёт строки левой таблицы, для которых не нашлось пары, например клиентов без заказов. Тот же результат даёт конструкция NOT EXISTS.

Есть ли FULL JOIN в MySQL?

Нет, MySQL не поддерживает FULL JOIN. Его заменяют объединением двух запросов через UNION: первый с LEFT JOIN, второй с RIGHT JOIN. В PostgreSQL, Microsoft SQL Server и Oracle FULL JOIN есть.

Сколько таблиц можно соединить в одном запросе?

Сколько угодно: каждый следующий JOIN присоединяет таблицу к уже полученному результату. На практике аналитики соединяют три-пять таблиц, а для больших запросов используют CTE через WITH, чтобы запрос оставался читаемым.

Закрепите JOIN на практике

На курсе «Обработка и анализ данных в SQL» вы решите задачи на соединение таблиц, агрегаты и подзапросы на данных, похожих на рабочие.

Что почитать дальше
Александр Вальцев
Автор статьи Александр Вальцев Сооснователь и CEO SF Education, эксперт по корпоративным финансам
Корп. финансы Финмоделирование Инвестиции EdTech Аналитика
10+ лет в EdTech
100 000+ студентов
×150 рост за 5 лет
1000+ часов контента
  • Сооснователь и CEO SF Education — ТОП-10 по качеству образования (РБК), ТОП-100 перспективных стартапов (HolonIQ)
  • 2 года в корпоративных финансах: private equity в Канаде, investment banking в России
  • Автор курсов и вебинаров по финансовому моделированию, лектор в вузах, организатор кейс-чемпионатов в Казахстане и Узбекистане
Образование: University of Toronto (BCom in Finance), CFA Level 1