JOIN и операции множеств: вопросы для собеседования (часть 3)

JOIN-ы — фундамент аналитического SQL. INNER, LEFT, RIGHT, FULL OUTER, CROSS JOIN, а также UNION, INTERSECT, EXCEPT — на собеседовании нужно не просто знать синтаксис, но и понимать, что происходит при дубликатах ключей и NULL-значениях. Задачи на JOIN встречаются на каждом собеседовании без исключения.

Агрегация, GROUP BY и HAVINGДаты и времяEXPLAIN и оптимизацияВыражения и NULLОсновы SQL-запросовСтроки и приведение типовПодзапросы и CTEОконные функции

Вопросы 1115 из 40

11Продажи хранятся в двух таблицах: `online_sales` и `offline_sales` с одинаковой структурой. Нужно получить общую выручку по каждому продукту. Какой паттерн корректен?
AСоединить обе таблицы через `INNER JOIN` по `product_id` и сложить суммы в одном `SUM`
BНаписать два отдельных `SELECT` с `GROUP BY` и объединить через `UNION` с дедупликацией
CИспользовать `FULL OUTER JOIN` по `product_id` — он автоматически сложит суммы из обеих таблиц
DОбъединить строки через `UNION ALL`, затем сгруппировать и агрегировать общий результат
Ответ: `UNION ALL` склеивает строки из обеих таблиц, а внешний `GROUP BY` с `SUM` считает общий итог: `SELECT product_id, SUM(amount) FROM (...UNION ALL...) GROUP BY product_id`.

Паттерн «UNION ALL + GROUP BY»: сначала `UNION ALL` объединяет сырые строки из нескольких источников, затем внешний `SELECT` с `GROUP BY` агрегирует. `JOIN` здесь не подходит — если продукт есть в обеих таблицах, `INNER JOIN` дублирует строки и завысит сумму. `UNION` (без ALL) удалит строки с одинаковыми суммами — тоже ошибка. `FULL OUTER JOIN` не складывает значения автоматически.

12Таблица `sessions` и таблица `purchases` содержат `user_id` и `date`. Нужно соединить данные так, чтобы каждой сессии соответствовала покупка того же пользователя в тот же день. Как записать `JOIN`?
AУказать оба условия в `ON`: `ON a.user_id = b.user_id AND a.date = b.date` для точного соответствия
BСоединить по `user_id` в `ON` и отфильтровать по дате в `WHERE` — результат будет тот же
CУказать оба условия в `WHERE`: `WHERE a.user_id = b.user_id AND a.date = b.date` через запятую
DСоединить по одному столбцу в `ON` и добавить `HAVING a.date = b.date` для второго условия
Ответ: Несколько условий в `ON` через `AND` обеспечивают соединение по составному ключу: `ON a.user_id = b.user_id AND a.date = b.date`.

Если совпадение требуется по нескольким столбцам, все условия указываются в `ON` через `AND`. Это аналог соединения по составному ключу. Для `INNER JOIN` перенос условия в `WHERE` даст тот же результат, но для `LEFT JOIN` — нет: условие в `WHERE` отфильтрует строки с `NULL` и превратит внешнее соединение во внутреннее. Поэтому рекомендуется всегда указывать условия соединения в `ON`.

13Аналитик переписал запрос, поменяв порядок таблиц в цепочке `JOIN`. Запрос стал выполняться быстрее. Почему это могло произойти?
AПорядок таблиц в `FROM` строго определяет порядок соединения — первая таблица всегда ведущая
BОптимизатор PostgreSQL может изменить порядок `JOIN` для улучшения производительности
CТаблицы всегда соединяются справа налево — последняя в списке обрабатывается первой
DПорядок `JOIN` влияет на результат запроса — меняя его, можно получить другие строки
Ответ: Оптимизатор PostgreSQL обычно сам выбирает оптимальный порядок соединения, но при большом числе таблиц может не найти лучший план — и ручная перестановка помогает.

Для `INNER JOIN` порядок таблиц не влияет на результат — это коммутативная операция. Оптимизатор перебирает варианты порядка соединения и выбирает лучший план. Но при 8+ таблицах полный перебор отключается (параметр `join_collapse_limit`), и оптимизатор следует порядку из запроса. В этом случае ручная перестановка может улучшить план. Для `OUTER JOIN` порядок влияет на результат — их оптимизатор не переставляет.

14Какое утверждение про `RIGHT JOIN` верно в аналитических запросах?
A`RIGHT JOIN` можно заменить на `LEFT JOIN`, поменяв таблицы местами.
B`RIGHT JOIN` всегда быстрее `LEFT JOIN` на тех же данных.
C`RIGHT JOIN` автоматически убирает дубликаты после соединения.
D`RIGHT JOIN` — это то же самое, что `UNION`.
Ответ: `RIGHT JOIN` — это симметричный вариант `LEFT JOIN`: меняете местами таблицы и получаете эквивалентный запрос.

По смыслу `RIGHT JOIN` сохраняет все строки из правой таблицы. Это эквивалентно `LEFT JOIN`, если переставить таблицы: `A RIGHT JOIN B` ↔ `B LEFT JOIN A`. Поэтому `RIGHT JOIN` часто избегают: он ухудшает читаемость, а функционально почти не даёт преимуществ.

15Какое условие обязательно, чтобы запрос с `UNION` был корректным?
AОбе выборки должны быть отсортированы одинаковым `ORDER BY`.
BОбе выборки должны вернуть одинаковое количество строк.
CОбе выборки должны вернуть одинаковое количество колонок с совместимыми типами в соответствующих позициях.
DОбе выборки должны использовать одинаковые имена таблиц.
Ответ: `UNION` объединяет результаты построчно, поэтому у обеих частей должны совпадать «форма» (число колонок и их типы).

Операции над наборами (`UNION`, `INTERSECT`, `EXCEPT`) работают между двумя запросами, которые возвращают одинаковое число колонок. Типы данных соответствующих колонок должны быть совместимы (например, `int` с `bigint`, `text` с `varchar`). Названия колонок и сортировка не обязаны совпадать.

12345678

Хотите тренировать интерактивно?

В приложении — таймер, прогресс, стрики и 1700+ вопросов по всем темам.

Тренировать в Telegram

Другие темы: SQL

Агрегация, GROUP BY и HAVINGДаты и времяEXPLAIN и оптимизацияВыражения и NULLОсновы SQL-запросовСтроки и приведение типовПодзапросы и CTEОконные функции