В чем разница между UNION и UNION ALL в SQL?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
UNION vs UNION ALL в SQL: объединение результатов запросов
UNION и UNION ALL — это операторы SQL для объединения результатов двух или нескольких SELECT запросов в один результирующий набор. Они выглядят похоже, но имеют важное различие.
UNION: объединение с удалением дубликатов
UNION объединяет результаты запросов и удаляет дублирующиеся строки из финального набора.
Синтаксис:
SELECT column1, column2 FROM table1
UNION
SELECT column1, column2 FROM table2
Пример:
SELECT id, name FROM users WHERE country = 'US'
UNION
SELECT id, name FROM users WHERE country = 'CA'
Если в US и CA одинаковые пользователи, они появятся в результате только один раз.
Результат:
id name
1 Alice
2 Bob
3 Charlie
UNION ALL: объединение со всеми дубликатами
UNION ALL объединяет результаты и сохраняет все строки, включая дубликаты.
Синтаксис:
SELECT column1, column2 FROM table1
UNION ALL
SELECT column1, column2 FROM table2
Пример с тем же запросом:
SELECT id, name FROM users WHERE country = 'US'
UNION ALL
SELECT id, name FROM users WHERE country = 'CA'
Результат:
id name
1 Alice
2 Bob
3 Charlie
1 Alice (дубликат! из CA)
Таблица сравнения
| Свойство | UNION | UNION ALL |
|---|---|---|
| Дубликаты | Удаляет | Сохраняет |
| Производительность | Медленнее (нужен sort) | Быстрее (просто конкатенация) |
| Использование памяти | Выше (для дедупликации) | Ниже |
| Совпадающие столбцы | Требует совпадения | Требует совпадения |
| Порядок строк | Может изменяться | Сохраняется исходный |
Когда использовать UNION
Используй UNION когда:
- Ты хочешь уникальные значения
- Объединяешь данные из разных источников (например, active и inactive пользователи)
- Небольшой объём данных (< 1M строк)
Пример:
-- Найти всех пользователей, которые либо совершили покупку, либо оставили отзыв
SELECT user_id FROM orders
UNION
SELECT user_id FROM reviews
-- Результат: только уникальные user_id
Когда использовать UNION ALL
Используй UNION ALL когда:
- Тебе нужны все строки, включая дубликаты
- Большой объём данных (нужна производительность)
- Ты сам отфильтруешь дубликаты позже
Пример:
-- Получить все события пользователей из разных сервисов
SELECT user_id, event_type, created_at FROM web_events
UNION ALL
SELECT user_id, event_type, created_at FROM mobile_events
UNION ALL
SELECT user_id, event_type, created_at FROM api_events
-- Результат: все события, если пользователь совершил одно действие в трёх сервисах
-- Это даст 3 строки для одного действия
Практические примеры
Пример 1: RFM анализ объединения источников
-- Собрать покупки с веб-сайта и мобильного приложения
WITH web_purchases AS (
SELECT user_id, purchase_amount, purchase_date, 'web' as source
FROM web_orders
WHERE purchase_date >= CURRENT_DATE - INTERVAL 90 DAY
),
mobile_purchases AS (
SELECT user_id, purchase_amount, purchase_date, 'mobile' as source
FROM mobile_orders
WHERE purchase_date >= CURRENT_DATE - INTERVAL 90 DAY
)
SELECT
user_id,
COUNT(*) as total_purchases,
SUM(purchase_amount) as total_spent,
COUNT(DISTINCT source) as sources_count
FROM (
SELECT * FROM web_purchases
UNION ALL -- Нужны все покупки, даже если дублируются
SELECT * FROM mobile_purchases
)
GROUP BY user_id
ORDER BY total_spent DESC
Пример 2: Уникальные пользователи с разных платформ
-- Найти пользователей, активных ЛИБО на веб, ЛИБО на мобиле
SELECT user_id
FROM (
SELECT DISTINCT user_id FROM web_sessions
WHERE session_date >= CURRENT_DATE - 7
UNION -- Только уникальные (дубликаты удалены)
SELECT DISTINCT user_id FROM mobile_sessions
WHERE session_date >= CURRENT_DATE - 7
)
ORDER BY user_id
-- Результат: каждый user_id появится только один раз
Пример 3: Комбинирование UNION и UNION ALL
-- Стратегия для больших данных
SELECT
user_id,
'web' as platform,
COUNT(*) as events,
SUM(spent) as total_spent
FROM web_events
WHERE event_date >= CURRENT_DATE - 90
GROUP BY user_id
UNION ALL -- Быстро объединяем
SELECT
user_id,
'mobile' as platform,
COUNT(*) as events,
SUM(spent) as total_spent
FROM mobile_events
WHERE event_date >= CURRENT_DATE - 90
GROUP BY user_id
Требования для UNION и UNION ALL
- Одинаковое количество столбцов
-- Правильно: 3 столбца в обоих запросах
SELECT id, name, age FROM users
UNION
SELECT user_id, user_name, user_age FROM customers
-- Ошибка: 3 столбца vs 2 столбца
SELECT id, name, age FROM users
UNION
SELECT user_id, user_name FROM customers -- ERROR!
- Совместимые типы данных
-- Правильно: обе числовые
SELECT id FROM users
UNION
SELECT customer_id FROM customers
-- Потенциальная ошибка: int и string несовместимы
SELECT age FROM users -- int
UNION
SELECT name FROM customers -- string - ОШИБКА в строгих БД
- Порядок столбцов важен
-- Результирующие названия столбцов берутся из ПЕРВОГО запроса
SELECT user_id, user_name FROM users
UNION
SELECT customer_id, customer_name FROM customers
-- Результат будет иметь названия: user_id, user_name (из первого SELECT)
Оптимизация производительности
-- Медленно: UNION требует сортировки для дедупликации
SELECT id FROM table1
UNION
SELECT id FROM table2
-- Быстрее: UNION ALL если уверен в отсутствии дубликатов
SELECT id FROM table1
UNION ALL
SELECT id FROM table2
-- Очень быстро: используй индексы
SELECT id FROM table1
WHERE id NOT IN (SELECT id FROM table2)
UNION ALL
SELECT id FROM table2
Совет для Product Analysts
Для анализа используй UNION ALL по умолчанию:
- Быстрее выполняется
- Проще отлаживать
- Если нужны уникальные значения, используй
DISTINCTпослеUNION ALL
-- Вместо медленного UNION
SELECT DISTINCT user_id
FROM (
SELECT user_id FROM web_orders
UNION ALL
SELECT user_id FROM mobile_orders
)
-- Это часто быстрее, чем UNION