В чём разница между UNION и UNION ALL?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
UNION vs UNION ALL: объединение результатов запросов
UNION и UNION ALL — это операции для объединения результатов двух или более SELECT запросов в один результат.
Основная разница: UNION удаляет дубликаты, UNION ALL сохраняет все.
Простой пример
-- Таблица 1: Текущие сотрудники
SELECT name, department
FROM current_employees;
Результат:
name | department
Alice | Sales
Bob | Engineering
Charlie | Sales
-- Таблица 2: Бывшие сотрудники
SELECT name, department
FROM former_employees;
Результат:
name | department
Diana | Sales
Eric | Engineering
Alice | Sales ← Эта Alice была раньше
-- Теперь объединяю:
SELECT name, department FROM current_employees
UNION
SELECT name, department FROM former_employees;
Результат (Alice одна раз, потому что UNION удаляет дубликаты):
name | department
Alice | Sales ← одна строка
Bob | Engineering
Charlie | Sales
Diana | Sales
Eric | Engineering
Всего: 5 строк
-- Тот же запрос с UNION ALL
SELECT name, department FROM current_employees
UNION ALL
SELECT name, department FROM former_employees;
Результат (Alice два раза):
name | department
Alice | Sales
Bob | Engineering
Charlie | Sales
Diana | Sales
Eric | Engineering
Alice | Sales ← вторая Alice
Всего: 6 строк
Таблица сравнения
| Параметр | UNION | UNION ALL |
|---|---|---|
| Дубликаты | Удаляет | Сохраняет |
| Производительность | Медленнее (нужно сортировать для удаления дубликатов) | Быстрее |
| Когда использовать | Когда нужны уникальные значения | Когда нужны все значения |
Когда использовать UNION
UNION используй когда нужны УНИКАЛЬНЫЕ значения:
-- Пример: найти всех пользователей которые либо сделали покупку,
-- либо зарегистрировались в приложении
SELECT user_id FROM orders
UNION
SELECT user_id FROM app_registrations;
-- Если user_id в обеих таблицах, он появится один раз
-- Результат: список уникальных пользователей
Техническая реализация:
Шаг 1: Выполню первый SELECT
Шаг 2: Выполню второй SELECT
Шаг 3: Объединю результаты
Шаг 4: Отсортирую и удалю дубликаты (expensive!)
Когда использовать UNION ALL
UNION ALL используй когда дубликаты важны или нужна скорость:
-- Пример: объединить логи ошибок из разных систем
SELECT error_id, error_msg, timestamp FROM system_a_errors
UNION ALL
SELECT error_id, error_msg, timestamp FROM system_b_errors
UNION ALL
SELECT error_id, error_msg, timestamp FROM system_c_errors;
-- Мне нужны ВСЕ ошибки из всех систем
-- Если система выдала одну и ту же ошибку дважды, это важно
-- UNION ALL будет быстрее
Практические примеры
Пример 1: Объединение данных из разных источников
-- Продажи из разных магазинов
SELECT
order_id,
customer_id,
amount,
'store_a' as source
FROM store_a_orders
WHERE date >= '2024-01-01'
UNION ALL ← использую UNION ALL потому что нужны все продажи
SELECT
order_id,
customer_id,
amount,
'store_b' as source
FROM store_b_orders
WHERE date >= '2024-01-01'
UNION ALL
SELECT
order_id,
customer_id,
amount,
'store_c' as source
FROM store_c_orders
WHERE date >= '2024-01-01';
-- Результат: все продажи из всех магазинов
Пример 2: Объединение с фильтрацией дубликатов
-- Какие email'ы используются дважды? (в current и legacy базе)
SELECT email
FROM current_users
WHERE email IN (
SELECT email
FROM legacy_users
)
-- Другой способ через UNION
SELECT DISTINCT email ← фильтрую дубликаты после
FROM (
SELECT email FROM current_users
UNION ALL
SELECT email FROM legacy_users
) combined
GROUP BY email
HAVING COUNT(*) > 1; ← появляются больше одного раза
Пример 3: Комбинирование разных типов запросов
-- Объединить информацию о пользователях и гостях
SELECT
user_id,
'user' as type,
email,
created_at
FROM users
UNION
SELECT
guest_id,
'guest' as type,
email,
created_at
FROM guests;
-- Если пользователь и гость используют один email,
-- он появится один раз с первого SELECT
Требования к UNION
1. Одинаковое количество колонок
-- ✅ ПРАВИЛЬНО
SELECT id, name FROM users
UNION
SELECT id, name FROM archived_users; ← 2 колонки в обоих
-- ❌ НЕПРАВИЛЬНО
SELECT id, name, email FROM users
UNION
SELECT id, name FROM archived_users; ← 3 vs 2 колонок
2. Совместимые типы данных
-- ✅ ПРАВИЛЬНО
SELECT user_id (INT), email (VARCHAR) FROM users
UNION
SELECT customer_id (INT), email (VARCHAR) FROM customers;
-- ❌ НЕПРАВИЛЬНО
SELECT user_id (INT), email (VARCHAR) FROM users
UNION
SELECT email (VARCHAR), user_id (INT) FROM others; ← порядок важен!
Производительность
-- Тест на 1M строк
SELECT id, amount FROM table_a
UNION
SELECT id, amount FROM table_b;
-- Время: 2.5 сек
-- Операции: scan + sort + distinct (дорого!)
SELECT id, amount FROM table_a
UNION ALL
SELECT id, amount FROM table_b;
-- Время: 0.8 сек (3x быстрее!)
-- Операции: scan + scan (просто соединение)
Правило: Используй UNION ALL по умолчанию, UNION только если нужны уникальные значения.
Альтернатива UNION — CONCAT или JOIN
-- Вместо UNION для объединения похожих таблиц
-- Способ 1: UNION (выше)
SELECT * FROM users
UNION ALL
SELECT * FROM archived_users;
-- Способ 2: FULL OUTER JOIN (если есть общий key)
SELECT COALESCE(u.id, a.id) as id,
u.name as current_name,
a.name as archived_name
FROM users u
FULL OUTER JOIN archived_users a ON u.id = a.id;
-- Способ 3: CTE (более читаемо)
WITH all_users AS (
SELECT * FROM users
UNION ALL
SELECT * FROM archived_users
)
SELECT * FROM all_users WHERE ...;
Вывод
UNION vs UNION ALL:
- UNION — удаляет дубликаты (медленнее, безопаснее)
- UNION ALL — сохраняет все (быстрее, может быть дубликаты)
Когда использовать:
- UNION: дважды нужны уникальные значения
- UNION ALL: объединение всех данных из разных источников
Памятка:
Если сомневаешься → использови UNION ALL
Это быстрее, и ты всегда можешь добавить DISTINCT после если нужно.
SELECT DISTINCT ... FROM (
SELECT * FROM table1
UNION ALL
SELECT * FROM table2
);
Производительность: UNION ALL в 3-10x быстрее UNION на большых объёмах, потому что не требует sorting и duplicate detection.