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

В чем разница между UNION и UNION ALL в SQL?

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

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

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

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

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)

Таблица сравнения

СвойствоUNIONUNION ALL
ДубликатыУдаляетСохраняет
ПроизводительностьМедленнее (нужен sort)Быстрее (просто конкатенация)
Использование памятиВыше (для дедупликации)Ниже
Совпадающие столбцыТребует совпаденияТребует совпадения
Порядок строкМожет изменятьсяСохраняется исходный

Когда использовать UNION

Используй UNION когда:

  1. Ты хочешь уникальные значения
  2. Объединяешь данные из разных источников (например, active и inactive пользователи)
  3. Небольшой объём данных (< 1M строк)

Пример:

-- Найти всех пользователей, которые либо совершили покупку, либо оставили отзыв
SELECT user_id FROM orders
UNION
SELECT user_id FROM reviews

-- Результат: только уникальные user_id

Когда использовать UNION ALL

Используй UNION ALL когда:

  1. Тебе нужны все строки, включая дубликаты
  2. Большой объём данных (нужна производительность)
  3. Ты сам отфильтруешь дубликаты позже

Пример:

-- Получить все события пользователей из разных сервисов
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

  1. Одинаковое количество столбцов
-- Правильно: 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!
  1. Совместимые типы данных
-- Правильно: обе числовые
SELECT id FROM users
UNION
SELECT customer_id FROM customers

-- Потенциальная ошибка: int и string несовместимы
SELECT age FROM users        -- int
UNION
SELECT name FROM customers   -- string - ОШИБКА в строгих БД
  1. Порядок столбцов важен
-- Результирующие названия столбцов берутся из ПЕРВОГО запроса
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