← Назад к вопросам

Как объединить два SELECT-запроса?

1.6 Junior🔥 281 комментариев
#SQL и базы данных

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Объединение двух SELECT-запросов

В SQL существует несколько способов объединить результаты двух SELECT-запросов. Выбор метода зависит от структуры данных, взаимосвязи таблиц и типа объединения.

1. UNION и UNION ALL

UNION объединяет результаты двух запросов, удаляя дубликаты.

SELECT id, name, role FROM employees WHERE department = "Sales"
UNION
SELECT id, name, role FROM managers WHERE status = "active";

UNION ALL объединяет результаты, сохраняя дубликаты (быстрее, чем UNION).

SELECT id, name, amount FROM transactions_2024
UNION ALL
SELECT id, name, amount FROM transactions_2025;

Требования для UNION:

  • Одинаковое количество колонок
  • Совместимые типы данных
  • Имена колонок берутся из первого SELECT

2. JOIN (внутреннее объединение таблиц)

Если две таблицы имеют общий ключ, используй JOIN.

INNER JOIN возвращает только совпадающие строки:

SELECT u.id, u.name, o.order_id, o.amount
FROM users u
INNER JOIN orders o ON u.id = o.user_id
WHERE o.status = "completed";

LEFT JOIN все строки из первой таблицы + совпадающие из второй:

SELECT u.id, u.name, COUNT(o.order_id) as order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id, u.name;

3. Сравнение подходов

Таблица 1: Продажи 2024 Результат: (1, 100), (2, 200)

Таблица 2: Продажи 2025 Результат: (2, 150), (3, 300)

Унион ALL (объединение рядов):

SELECT user_id, amount FROM sales_2024
UNION ALL
SELECT user_id, amount FROM sales_2025;

Результат: (1, 100), (2, 200), (2, 150), (3, 300)

JOIN (объединение по ключу):
SELECT 
    COALESCE(a.user_id, b.user_id) as user_id,
    COALESCE(a.amount, 0) as amount_2024,
    COALESCE(b.amount, 0) as amount_2025
FROM sales_2024 a
FULL OUTER JOIN sales_2025 b ON a.user_id = b.user_id;

Результат: (1, 100, 0), (2, 200, 150), (3, 0, 300)

4. WITH (Common Table Expression)

WITH recent_orders AS (
    SELECT user_id, order_id, amount
    FROM orders
    WHERE created_at >= NOW() - INTERVAL "30 days"
),
frequent_users AS (
    SELECT user_id, COUNT(*) as order_count
    FROM orders
    GROUP BY user_id
    HAVING COUNT(*) > 5
)
SELECT ro.user_id, COUNT(ro.order_id) as recent
FROM recent_orders ro
LEFT JOIN frequent_users fu ON ro.user_id = fu.user_id
GROUP BY ro.user_id;

5. INTERSECT и EXCEPT

INTERSECT только строки в обоих результатах:

SELECT user_id FROM users_list_a
INTERSECT
SELECT user_id FROM users_list_b;

EXCEPT строки из первого, отсутствующие во втором:

SELECT user_id FROM all_users
EXCEPT
SELECT user_id FROM deleted_users;

6. Производительность

UNION: Медленнее (удаление дубликатов) - используй когда важны уникальные строки UNION ALL: Быстрее (нет дедупликации) - используй когда дубликаты допустимы INNER JOIN: Быстро (индексы на ключах) - используй для связанных данных LEFT JOIN: Среднее - используй когда важны все строки одной таблицы

WITH (CTE): Оптимизируется оптимайзером - лучше для читаемости

7. Оптимизация UNION запросов

Плохо (объединяет результаты, потом фильтрует):

(SELECT * FROM orders_2024
UNION
SELECT * FROM orders_2025)
WHERE status = "completed";

Хорошо (фильтрует перед объединением):

SELECT * FROM orders_2024 WHERE status = "completed"
UNION
SELECT * FROM orders_2025 WHERE status = "completed";

Заключение

Выбор метода объединения запросов зависит от структуры данных: UNION/UNION ALL для вертикального объединения, JOIN для горизонтального объединения по ключу, WITH для читаемости и сложных запросов, INTERSECT/EXCEPT для операций над множествами.

Как объединить два SELECT-запроса? | PrepBro