В блоге ГигаЧат разбираем один из самых часто используемых SQL-операторов — JOIN.
Операция JOIN в SQL — это механизм объединения данных из двух и более таблиц по общему признаку. Чаще всего признаком выступает общий идентификатор, внешний ключ или другое поле, значения которого совпадают в связанных таблицах.
В реляционных БД информация обычно распределяется между несколькими таблицами. Это нужно для повышения гибкости базы данных, уменьшения числа дубликатов и упрощения обновления. Но иногда нужно получить связанные сведения из нескольких таблиц — для этого используют JOIN.
Например, информация о клиентах может храниться в таблице Customers, а данные о заказах — в Orders. Если необходимо вывести список заказов вместе с именами покупателей, одной таблицы будет недостаточно. Но можно объединить записи по общему полю и получить единый результат.
Важно понимать, что оператор не изменяет информацию в таблицах. Он работает только с результатом выборки, а соединение выполняется только во время исполнения SQL-запроса. Понимание логики работы механизма считается базовым знанием для начинающих разработчиков, поэтому лучше осознать его на первых этапах обучения.
Общая схема записи выглядит так:
SELECT столбцы
FROM первая_таблица
JOIN вторая_таблица
ON перваятаблица.общееполе = втораятаблица.общееполе;
SELECT определяет, какие столбцы необходимо вывести, FROM указывает основную таблицу, а JOIN — присоединяет вторую. ON задаёт условие соединения, по которому SQL определяет связанные записи.
Логику работы легче всего понять на примере. Допустим, есть две таблицы интернет-магазина, о которых мы говорили в первом разделе статьи.
Customers:
| customer_id | name |
|---|---|
| 1 | Илья Бажанов |
| 2 | Ирина Афанасьева |
| 3 | Виктор Иванов |
Orders:
| order_id | customer_id | amount |
|---|---|---|
| 101 | 1 | 15 000 |
| 102 | 1 | 24 000 |
| 103 | 3 | 1 900 |
Теперь объединим их с помощью SQL-запроса:
SELECT *
FROM Customers
JOIN Orders
ON Customers.customer_id = Orders.customer_id;
Здесь мы выбираем все столбцы. СУБД действует по такому алгоритму:
Цикл повторяется, пока не будут обработаны все строки.
Результат в нашем примере будет таким:
| name | order_id | amount |
|---|---|---|
| Илья Бажанов | 101 | 15 000 |
| Илья Бажанов | 102 | 24 000 |
| Виктор Иванов | 103 | 1 900 |
Илья Бажанов появляется дважды, поскольку у него было два заказа — оператор создает отдельную запись для каждого найденного совпадения.
Чтобы ускорить поиск совпадений, важно индексировать поля, по которым соединяются таблицы.
Это наиболее часто используемый тип соединения. Он возвращает только те строки, для которых были найдены совпадения в обеих таблицах. Если соответствующей записи нет хотя бы в одной, такая строка не попадет в результат. Пример именно с этим оператором мы привели в предыдущем пункте.
Оператор возвращает все строки из левой таблицы. Если соответствующая запись в правой отсутствует, SQL подставляет значение NULL.
Например, компания хранит в базе список сотрудников и данные о выданных им ноутбуках.
Employees:
| employee_id | employee |
|---|---|
| 1 | Алена Сидорова |
| 2 | Оксана Трофимова |
| 3 | Игорь Андреев |
Laptops:
| employee_id | laptop |
|---|---|
| 1 | ASUS |
| 2 | Lenovo |
Запрос будет выглядеть так:
SELECT e.employee, l.laptop
FROM Employees e
LEFT JOIN Laptops l
ON e.employee_id = l.employee_id;
В результате получим такие пары:
| employee | laptop |
|---|---|
| Алена Сидорова | ASUS |
| Оксана Трофимова | Lenovo |
| Игорь Андреев | NULL |
Оператор возвращает каждую запись из правой таблицы, даже если соответствующих данных для нескольких строк нет в левой. Рассмотрим пример с преподавателями и курсами, которые они ведут.
Teachers:
| teacher_id | teacher |
|---|---|
| 1 | Виталий Кузнецов |
| 2 | Марина Смирнова |
Courses:
| course_id | teacher_id | course |
|---|---|---|
| 101 | 1 | Python |
| 102 | 2 | Java |
| 103 | 3 | C++ |
Сформулируем SQL-запрос:
SELECT t.teacher, c.course
FROM Teachers t
RIGHT JOIN Courses c
ON t.teacher_id = c.teacher_id;
Результат:
| teacher | course |
|---|---|
| Виталий Кузнецов | Python |
| Марина Смирнова | Java |
| NULL | C++ |
Курс по C++ есть в итоговой таблице, несмотря на то что преподавателя с идентификатором 3 в Teachers нет.
Этот оператор объединяет возможности двух предыдущих: он возвращает все строки пары таблиц независимо от того, найдены ли совпадения. Приведем пример с информацией о покупателях и уровнях программы лояльности в базе данных.
Clients:
| client_id | client |
|---|---|
| 1 | Максим Комаров |
| 2 | Арина Емельянова |
| 3 | Ольга Малышева |
BonusCards:
| client_id | card |
|---|---|
| 2 | Gold |
| 4 | Platinum |
Запрос выглядит так:
SELECT c.client, b.card
FROM Clients c
FULL JOIN BonusCards b
ON c.client_id = b.client_id;
Результат:
| client | card |
|---|---|
| Максим Комаров | NULL |
| Арина Емельянова | Gold |
| Ольга Малышева | NULL |
| NULL | Platinum |
Этот вид сильно отличается от остальных: он не ищет совпадения, а соединяет каждую строку первой таблицы с каждой строкой второй. Допустим, магазин продает джинсы двух размеров и трех цветов.
Sizes:
| size |
|---|
| S |
| M |
Colors:
| color |
|---|
| Черный |
| Синий |
| Голубой |
Напишем SQL-запрос:
SELECT s.size, c.color
FROM Sizes s
CROSS JOIN Colors c;
Результат:
| size | color |
|---|---|
| S | Черный |
| S | Синий |
| S | Голубой |
| M | Черный |
| M | Синий |
| M | Голубой |
Количество строк равно произведению количества записей обеих таблиц (2 * 3 = 6).
ГигаЧат — это бесплатный ИИ-помощник от Сбера. Он умеет вести диалоги с пользователями, создавать картинки и видео, а также генерировать код.
С помощью ГигаЧата можно быстрее разобраться в логике работы JOIN и других операторов, понять различия между ними и научиться составлять сложные SQL-запросы. Помимо теории, нейросеть может сгенерировать задания для закрепления темы и проверить результат выполнения с объяснением каждой ошибки. Если писать код самостоятельно пока не получается, попросите у ГигаЧата примеры решения вашей задачи.
Все эти функции полезны для тех, кто только начинает изучение языка. Работать с нейросетью, получая развернутые ответы с пояснениями и примерами, гораздо быстрее, чем искать информацию в интернете.