JOIN позволяет объединять несколько таблиц в одном SELECT-запросе по определенному условию, обычно через ключевое слово ON. Подзапрос (или вложенный запрос) — это запрос, помещённый внутри другого запроса. JOIN лучше работает для объединения больших таблиц с хорошими индексами, он более прозрачен для оптимизатора и обычно выполняется быстрее. Подзапросы удобны при необходимости вычисления агрегатов или при наличии условий, невозможных через JOIN (например, коррелированные запросы).
Пример JOIN:
SELECT employees.name, departments.name FROM employees JOIN departments ON employees.dept_id = departments.id;
Пример подзапроса:
SELECT name FROM employees WHERE dept_id IN ( SELECT id FROM departments WHERE location = 'Moscow' );
“Считается ли, что использование подзапросов всегда медленнее, чем использование JOIN?”
Ответ: Нет, не всегда! Корректно написанные подзапросы зачастую оптимизатор преобразует во внутренние JOIN'ы. Кроме того, иногда подзапрос эффективнее — например, когда внешний запрос работает с небольшим набором данных, а подзапрос возвращает заранее агрегированные результаты.
Пример:
SELECT name, salary FROM employees WHERE salary > (SELECT AVG(salary) FROM employees);
Этот подзапрос будет выполнен один раз.
История
На большом проекте для отчёта использовались вложенные подзапросы вместо JOIN. При увеличении объёма данных запрос стал занимать несколько минут вместо секунд. После замены подзапросов на JOIN производительность выросла в 10 раз.
История
В одном проекте аналитик переписал запрос с GROUP BY в подзапрос, не заметив, что в результате стали появляться дубли на уровне JOIN. Это привело к некорректным данным в отчётах — суммы были завышены из-за картезианского произведения.
История
Использование коррелированного подзапроса во внешнем цикле (для каждой строки) привело к полной деградации производительности при росте таблицы. Решили через JOIN с агрегированием — время обработки запросов сократилось с часов до минут.