Вопросы по теме «JOIN и операции множеств»
JOIN-ы — фундамент аналитического SQL. INNER, LEFT, RIGHT, FULL OUTER, CROSS JOIN, а также UNION, INTERSECT, EXCEPT — на собеседовании нужно не просто знать синтаксис, но и понимать, что происходит при дубликатах ключей и NULL-значениях. Задачи на JOIN встречаются на каждом собеседовании без исключения.
Всего в этом разделе 40 вопросов. Каждый — с правильным ответом и кратким разбором теории. Разбито на 8 частей по 5 вопросов.
Вопросы 1–5 из 40
1Аналитик написал `SELECT * FROM orders, users` без `WHERE` и без `JOIN ... ON`. В `orders` 1000 строк, в `users` 500 строк. Что вернёт запрос?
AЗапрос вернёт только строки из `orders`, где `user_id` совпадает с `id` в таблице `users`
BЗапрос вернёт ошибку выполнения, потому что не указано условие соединения двух таблиц
CКаждая строка `orders` соединится с каждой строкой `users` — получится декартово произведение
DЗапрос вернёт строки из `orders` с `NULL` вместо данных `users` — как при `LEFT JOIN` без условия
Ответ: Перечисление таблиц через запятую без условия — это неявный `CROSS JOIN`, который создаёт декартово произведение: 1000 × 500 = 500 000 строк.
Синтаксис `FROM a, b` без `WHERE` эквивалентен `FROM a CROSS JOIN b` — каждая строка первой таблицы соединяется с каждой строкой второй. Это классическая ошибка: аналитик забыл указать `WHERE orders.user_id = users.id`. Результат — 500 000 строк вместо ожидаемых 1000. Всегда проверяйте наличие условия соединения.
2В отчёте нужно вывести всех пользователей и количество их заказов, включая тех, у кого заказов нет. Какой тип соединения между `users` и `orders` по `user_id` нужен?
AИспользовать `INNER JOIN`
BИспользовать `LEFT JOIN`
CИспользовать `RIGHT JOIN`
DИспользовать `UNION`
Ответ: `LEFT JOIN` сохраняет все строки из левой таблицы и подставляет `NULL` для отсутствующих совпадений справа.
`INNER JOIN` вернёт только пользователей, у которых нашлись заказы. Для аналитических отчётов часто важно показать и пользователей без заказов (например, чтобы их метрика была 0). Для этого берут `users` слева и делают `LEFT JOIN` на `orders` по `user_id`.
3Нужно построить отчёт: по каждому продукту и каждому дню месяца — сумма продаж, включая дни с нулевыми продажами. Как сформировать каркас из всех пар дата-продукт?
AИспользовать `CROSS JOIN` между таблицей дат и таблицей продуктов для всех пар
BИспользовать `INNER JOIN` между таблицей дат и продуктов по общему ключу связи
CИспользовать `LEFT JOIN` таблицы продуктов к таблице дат по столбцу `created_at`
DИспользовать `UNION ALL` для объединения таблицы дат и продуктов в один результат
Ответ: `CROSS JOIN` генерирует декартово произведение двух таблиц — каждая дата сочетается с каждым продуктом, что даёт полный каркас для `LEFT JOIN` к продажам.
`CROSS JOIN` создаёт все возможные комбинации строк из двух таблиц: если дат 30 и продуктов 5, получится 150 строк. Затем этот каркас соединяют через `LEFT JOIN` с таблицей продаж — для дней без продаж будут `NULL`, которые заменяют на 0 через `COALESCE`. Это стандартный паттерн «date spine» в аналитике.
4Первый набор содержит значения: `100, 100, 100, 200`. Второй набор: `100, 300`. Чем отличаются результаты `EXCEPT` и `EXCEPT ALL`?
A`EXCEPT` вернёт `{200}`, а `EXCEPT ALL` вернёт `{100, 100, 200}` — три строки с учётом кратности
BОба запроса вернут одинаковый результат: одну строку со значением `200` без дубликатов
CОба запроса вернут `{100, 100, 200}`, потому что оператор вычитания не убирает дубликаты
D`EXCEPT` вернёт `{100, 200}`, а `EXCEPT ALL` вернёт пустой результат из-за пересечения
Ответ: `EXCEPT` дедуплицирует и вычитает множества — вернёт только `{200}`. `EXCEPT ALL` учитывает кратность: из 3 копий `100` вычтёт 1, оставит `{100, 100, 200}`.
`EXCEPT` работает как множественное вычитание: сначала дедуплицирует оба набора, затем убирает совпадения. Уникальные в первом: `{100, 200}`, `100` есть во втором — остаётся `{200}`. `EXCEPT ALL` работает по кратности: 3 копии `100` минус 1 копия `100` = 2 копии `100`, плюс `200` = `{100, 100, 200}`. Это аналогично разнице между `UNION` и `UNION ALL`.
5Два запроса: `SELECT * FROM orders JOIN users ON orders.user_id = users.user_id` и `SELECT * FROM orders JOIN users USING(user_id)`. В чём ключевое ограничение `USING`?
AСинтаксис `USING` позволяет соединять по столбцам с разными именами в двух таблицах
BСинтаксис `USING` требует, чтобы столбец соединения назывался одинаково в обеих таблицах
CСинтаксис `USING` работает только с `INNER JOIN` и не поддерживается для внешних соединений
DСинтаксис `USING` автоматически подбирает столбцы для соединения по совпадению типов данных
Ответ: `USING(col)` — сокращённый синтаксис для `ON`, который требует, чтобы столбец соединения имел одинаковое имя в обеих таблицах.
`USING(col)` эквивалентен `ON a.col = b.col`, но с двумя отличиями: столбец должен называться одинаково в обеих таблицах, и в результате `SELECT *` этот столбец появится один раз вместо двух. Если в одной таблице столбец называется `user_id`, а в другой `id`, `USING` не подойдёт — нужен `ON`.
Хотите тренировать интерактивно?
В приложении — таймер, прогресс, стрики и 1700+ вопросов по всем темам.
Тренировать в Telegram