Ответ
Хотя JOIN — основной инструмент для реляционных запросов, иногда нужны альтернативы. Вот методы, которые я использовал в зависимости от задачи:
1. Подзапросы (Subqueries) Идеально, когда результат из одной таблицы нужен только как условие для фильтрации в другой.
-- Найти всех пользователей, которые делали заказы (аналог INNER JOIN)
SELECT * FROM users
WHERE id IN (SELECT DISTINCT user_id FROM orders);
-- Найти товары, цена которых выше средней (связанность не через ключ)
SELECT * FROM products
WHERE price > (SELECT AVG(price) FROM products);
2. Операции над множествами: UNION / UNION ALL Используются для объединения результатов из разных таблиц с одинаковой структурой, а не для их связывания.
-- Объединить список email из двух таблиц (например, подписчики и клиенты)
SELECT email, 'subscriber' as source FROM newsletter_subscribers
UNION ALL -- UNION ALL не удаляет дубли, работает быстрее
SELECT email, 'customer' as source FROM customers;
-- Простой UNION удалит дублирующиеся строки.
3. Коррелированные подзапросы в SELECT или WHERE Позволяют "притянуть" одно значение из связанной таблицы для каждой строки основной.
-- Для каждого заказа получить имя клиента (менее эффективно, чем JOIN, но наглядно)
SELECT
id,
amount,
(SELECT name FROM clients WHERE clients.id = orders.client_id) as client_name
FROM orders;
4. Отдельные запросы + обработка на уровне приложения Иногда это оправдано:
- Для сложной, нереляционной логики, которую проще реализовать в коде.
- При работе с разнородными источниками данных (например, SQL + NoSQL).
- Для пагинации сложных объединённых данных, где
JOINможет работать медленно.
Пример (псевдокод на PHP):
$users = $pdo->query("SELECT id, name FROM users WHERE active = 1")->fetchAll();
$userIds = array_column($users, 'id');
$placeholders = implode(',', array_fill(0, count($userIds), '?'));
$orders = $pdo->prepare("SELECT * FROM orders WHERE user_id IN ($placeholders)");
$orders->execute($userIds);
$ordersData = $orders->fetchAll();
// Далее вручную сопоставляем users и orders в массиве $result
Когда что выбирать:
JOIN— для выборки связанных данных из разных таблиц в одной результирующей строке.- Подзапросы — для фильтрации или вычисления значений на основе другой таблицы.
UNION— для сложения наборов строк.- Отдельные запросы — когда реляционная модель не справляется или нужен полный контроль над производительностью.