- 17 октября 2026
- 8 минут
- 5
Статью подготовили специалисты образовательного сервиса Zaochnik.
Декартово произведение в SQL
Декартово произведение в SQL представляет собой полный набор всех комбинаций строк из двух и более таблиц, полученный путем попарного объединения каждой строки первой таблицы с каждой строкой второй. Такой результат формируется, если в операторе FROM перечислить таблицы через запятую без условий соединения.
Декартово произведение SQL - это результат объединения всех строк одной таблицы с каждой строкой другой таблицы, формирующий множество всех пар строк.
Механика работы устроена так: при выполнении запроса сервер СУБД создает временную таблицу в оперативной памяти, размер которой равен произведению количества строк исходных таблиц. Например, если в первой таблице 100 строк, а во второй 200, итоговая таблица будет содержать 20 000 строк. Каждая строка первой таблицы повторяется столько раз, сколько строк во второй, и наоборот.
Это значит, что при увеличении размера таблиц результат растет экспоненциально, что часто ведет к проблемам с производительностью и памятью.
На практике полное декартово произведение используется редко. Часто оно не несет полезной информации, так как объединяет данные без логической связи. Чаще требуется построение выборок с определёнными условиями соединения, исключающими бессмысленные комбинации.
Виды соединений таблиц в SQL
Чтобы ограничить выходное множество и получить осмысленные результаты, применяют различные виды соединений (JOIN). Существуют основные три типа:
- JOIN (INNER JOIN) — возвращает строки, у которых значения в объединяемых полях совпадают;
- LEFT JOIN — возвращает все строки из левой таблицы и совпадающие строки из правой, иначе NULL;
- RIGHT JOIN — возвращает все строки из правой таблицы и совпадающие из левой, иначе NULL.
Все они работают как подмножества декартова произведения, отбирая строки по ключам или условиям соединения. Механизм следующий: сервер СУБД при выполнении такого запроса сопоставляет строки на основе заданных связей, формирует новую таблицу, где каждая строка содержит данные из обеих исходных, связанные логически.
К примеру, если одна таблица содержит 1000 клиентов, а другая 500 заказов, JOIN по ключу клиента вернёт только те пары, где у клиента есть заказ. LEFT JOIN вернёт 1000 строк — для клиентов с заказами и для тех, у кого заказов нет (вторые будут с NULL в части заказа). При этом итоговый набор зависит от выбранного типа соединения.
Выражение таблица1 JOIN таблица2 - это выборка только строк с совпадающими значениями в ключевых полях обеих таблиц.
Выражение таблица1 LEFT JOIN таблица2 - это выборка всех строк таблицы 1 и только связанных со строками таблицы 2; при отсутствии связи строки таблицы 2 заменяются NULL.
Важно понимать, что RIGHT JOIN технически аналогичен LEFT JOIN, но наоборот: берутся все строки из правой таблицы и совпадающие из левой. Однако практически RIGHT JOIN часто заменяют LEFT JOIN для упрощения и оптимизации запросов.
RIGHT JOIN выполняется в среднем медленнее, чем LEFT JOIN, из-за особенностей алгоритмов построения результатов, что приводит к рекомендации по замене RIGHT JOIN на LEFT JOIN.
Пример запросов с JOIN и различия с полным декартовым произведением
Рассмотрим две таблицы: abiturient с данными абитуриентов и application с заявлениями на поступление. В application содержится внешний ключ на abiturient. Цель — получить таблицу, содержащую данные абитуриента и все его заявления.
Запрос с полным декартовым произведением будет выглядеть так:
SELECT * FROM abiturient, application;
Результат содержит число строк, равное произведению количества строк в обеих таблицах. Это бессмысленно, так как каждая строка первой таблицы связана с каждой второй вне зависимости от соответствия ключей.
Для получения связанных данных используется запрос с JOIN:
SELECT application.idapplication, application.spec, application.forma, abiturient.idabiturient, abiturient.fio, abiturient.birth_date, abiturient.age FROM application JOIN abiturient ON application.idabiturient = abiturient.idabiturient;
Этот запрос соединяет записи только там, где внешний ключ заявления совпадает с первичным ключом абитуриента. В результате окажутся только записи с совпадениями.
Если требуется видеть всех абитуриентов, включая не подававших заявлений, используют LEFT JOIN:
SELECT application.idapplication, application.spec, application.forma, abiturient.idabiturient, abiturient.fio, abiturient.birth_date, abiturient.age FROM abiturient LEFT JOIN application ON abiturient.idabiturient = application.idabiturient;
Здесь каждая строка из abiturient будет присутствовать, а для отсутствующих заявлений поля из application будут с NULL.
Разница между такими запросами важна: JOIN сужает выборку по совпадениям, LEFT JOIN расширяет её, включая отсутствующие связи справа. Это влияет на логику обработки и итоговые данные для анализа.
Оператор UNION и связь с FULL JOIN
В SQL есть несколько вариантов объединения наборов строк.
Оператор FULL JOIN, присутствующий не во всех СУБД, позволяет получить объединённый набор всех строк из обеих таблиц. Если строки связаны по ключу, они сливаются одной строкой, а отсутствующие с одной из сторон заполняются NULL. Механизм FULL JOIN можно реализовать с помощью оператора UNION, который соединяет два результата запросов.
Пример записи, эквивалентной FULL JOIN, может выглядеть так:
SELECT ... FROM table1 LEFT JOIN table2 ON ... UNION SELECT ... FROM table1 RIGHT JOIN table2 ON ...
UNION объединяет результаты двух запросов, исключая дубликаты. Механизм требует обрабатывать обе стороны соединения отдельно, а затем агрегировать. Это ведет к росту вычислительной нагрузки.
Следует учесть, что многие СУБД, например MySQL до версии 8.0, не поддерживают FULL JOIN. В таких случаях приходится использовать сложные конструкции с UNION для достижения аналогичного результата.
Матрица условий выбора метода соединения
Ниже приводится таблица, описывающая основные условия для выбора типа соединения и их технические ограничения:
| Ситуация | Рекомендуемый оператор | Особенности | Ограничения и ошибки |
|---|---|---|---|
| Нужно получить только связанные записи из двух таблиц | JOIN (INNER JOIN) | Отбирает строки с совпадающими ключами; исключает записи без связей | Записи без связей теряются; запрещены NULL в ключах без дополнительных условий |
| Нужно получить все из левой таблицы, с данными из правой, если есть | LEFT JOIN | Все строки левой таблицы присутствуют, в правой NULL где нет совпадений | При больших таблицах возможны повышенные затраты памяти; NULL могут требовать обработки в результатах |
| Все из правой таблицы и совпадающие левые | RIGHT JOIN | Аналогично LEFT JOIN; реализуется чаще с заменой на LEFT JOIN | RIGHT JOIN медленнее; лучше избегать в производственном коде |
| Нужно получить все записи из обеих таблиц с объединением связей | FULL JOIN или UNION | Включает записи без парной связи из обеих таблиц | FULL JOIN поддерживается не всеми СУБД; UNION повышает сложность и нагрузку |
Пользователю важно выбирать вид соединения, исходя из требований к данным и особенностей используемой СУБД. Некорректное применение типа соединения чаще всего ведет к получению лишних или потерянных строк.