UNION: примеры (SQL)
UNION(query1 UNION [ALL] query2): Depends on queriesОсновные сведения о UNION
Оператор UNION в MS SQL Server предназначен для объединения результирующих наборов данных из двух и более SELECT-запросов в один общий набор. Основная задача оператора — вертикальное соединение строк.
Применение UNION актуально в ситуациях, когда необходимо агрегировать данные из разных таблиц или запросов, имеющих схожую структуру. Частые сценарии использования включают консолидацию отчетов, объединение архивных и текущих данных, а также сбор информации из партиционированных таблиц.
По умолчанию оператор выполняет удаление дублирующихся строк из финального результата. Это поведение соответствует использованию необязательного ключевого слова DISTINCT. Альтернативный вариант — UNION ALL — объединяет результаты без проверки на дубликаты, что повышает производительность.
Основные требования к объединяемым запросам:
- Количество столбцов в каждом SELECT должно быть одинаковым.
- Соответствующие столбцы должны иметь совместимые типы данных.
- Имена столбцов в итоговом наборе берутся из первого запроса.
Оператор не имеет аргументов в классическом понимании, но работает с парами или цепочками SELECT-запросов. Результатом выполнения всегда является таблица с указанным количеством столбцов, содержащая строки из всех объединенных запросов.
Базовые примеры использования
Объединение данных из двух таблиц с удалением дублей:
SELECT 'Сотрудник' AS Тип, Имя, Фамилия FROM Сотрудники
UNION
SELECT 'Клиент', Имя, Фамилия FROM Клиенты
ORDER BY Фамилия;Тип | Имя | Фамилия -----------|-------|--------- Сотрудник | Иван | Петров Клиент | Анна | Сидорова Сотрудник | Петр | Иванов Клиент | Ольга | Петрова
Использование UNION ALL для сохранения всех строк, включая повторяющиеся:
SELECT Город FROM Филиалы WHERE Регион = 'Центр'
UNION ALL
SELECT Город FROM Клиенты WHERE Регион = 'Центр';Город --------- Москва Воронеж Москва Тула Москва
Объединение данных с агрегацией:
SELECT Год, SUM(Продажи) AS Сумма FROM Продажи_2023 GROUP BY Год
UNION
SELECT Год, SUM(Продажи) FROM Продажи_2024 GROUP BY Год;Год | Сумма ----|------ 2023| 150000 2024| 180000
Схожие операторы MS SQL
UNION ALL — базовая альтернатива UNION. Не выполняет проверку на дубликаты, что делает его быстрее. Рекомендуется к использованию, когда уникальность строк гарантирована или не требуется.
EXCEPT — возвращает строки из первого запроса, которые отсутствуют в результате второго. Удаляет дубликаты. Полезен для поиска различий между наборами данных.
SELECT ID FROM Таблица1
EXCEPT
SELECT ID FROM Таблица2;INTERSECT — возвращает только общие строки для всех объединенных запросов. Также удаляет дубликаты. Применяется для поиска пересечений.
SELECT Продукт FROM Заказы_Январь
INTERSECT
SELECT Продукт FROM Заказы_Февраль;Выбор между операторами зависит от задачи: UNION для объединения, EXCEPT для вычитания, INTERSECT для поиска совпадений.
Аналоги в других СУБД
MySQL / PostgreSQL: Поддерживают стандартные UNION, UNION ALL, EXCEPT (в MySQL — только через LEFT JOIN), INTERSECT. Синтаксис идентичен SQL Server.
-- PostgreSQL пример
SELECT a FROM t1
UNION
SELECT b FROM t2;Oracle: Операторы UNION, UNION ALL, MINUS (аналог EXCEPT), INTERSECT. Особенность — необходимость совместимости типов данных, включая VARCHAR2 и CHAR.
-- Oracle пример
SELECT имя FROM сотрудники
UNION ALL
SELECT название FROM отделы;SQLite: Полная поддержка UNION, UNION ALL. INTERSECT и EXCEPT появились с версии 3.22.0. Ограничения по сложности запросов меньше, чем в других СУБД.
-- SQLite пример
SELECT * FROM из_таблицы1
UNION
SELECT * FROM из_таблицы2;Sybase ASE: Использует аналогичный MS SQL синтаксис для UNION и UNION ALL. Поддержка INTERSECT и EXCEPT может требовать определенных настроек совместимости.
Основные отличия между платформами часто касаются обработки типов данных, сортировки NULL-значений и производительности при больших объемах информации.
Распространенные ошибки
Несовпадение числа столбцов в объединяемых запросах вызывает критическую ошибку.
SELECT ID, Имя FROM Сотрудники
UNION
SELECT ID FROM Клиенты; -- ОшибкаСообщение 205, уровень 16, состояние 1 Все запросы в операторе UNION должны иметь равное число выражений в списке целей.
Несовместимость типов данных в соответствующих столбцах.
SELECT ДатаРождения FROM Сотрудники -- тип DATE
UNION
SELECT Имя FROM Клиенты; -- тип NVARCHAR. Ошибка.Некорректное использование ORDER BY в отдельных запросах. ORDER BY применяется только к общему результату.
SELECT * FROM Таблица1 ORDER BY Поле1
UNION
SELECT * FROM Таблица2; -- ORDER BY в первом запросе не допускаетсяПутаница между UNION и UNION ALL, приводящая к неожиданной потере данных или снижению производительности.
-- Медленнее, если дубликаты не важны
SELECT Город FROM Таблица1
UNION -- Выполняет лишнюю проверку на уникальность
SELECT Город FROM Таблица2;Изменения в последних версиях
В SQL Server 2017 и более новых версиях существенных изменений синтаксиса оператора UNION не произошло. Основные улучшения касаются оптимизации производительности:
- Улучшенный обработчик запросов эффективнее объединяет результаты при использовании UNION ALL с большим количеством ветвей.
- Интеллектуальные функции обработки столбцов с разными типами данных, но совместимыми доменами.
- Лучшая интеграция с системами обработки columnstore-индексов при объединении наборов данных.
Для использования актуальных возможностей оптимизации рекомендуется применять последние накопительные обновления SQL Server.
Расширенные примеры применения
Объединение данных из более чем двух источников с группировкой итогового результата:
SELECT Регион, SUM(Сумма) AS Общий_объем
FROM (
SELECT Регион, Сумма FROM Продажи_2022
UNION ALL
SELECT Регион, Сумма FROM Продажи_2023
UNION ALL
SELECT Регион, Сумма FROM Продажи_2024
) AS Все_годы
GROUP BY Регион
HAVING SUM(Сумма) > 1000000;Использование UNION внутри CTE (обобщенного табличного выражения) для рекурсивных запросов:
WITH Иерархия AS (
SELECT ID, Имя, Родитель_ID, 1 AS Уровень
FROM Сотрудники
WHERE Родитель_ID IS NULL
UNION ALL
SELECT e.ID, e.Имя, e.Родитель_ID, h.Уровень + 1
FROM Сотрудники e
INNER JOIN Иерархия h ON e.Родитель_ID = h.ID
)
SELECT * FROM Иерархия;Создание сводной таблицы с разметкой строки с помощью фиктивных столбцов:
SELECT ID, Имя, 'Активен' AS Статус FROM Сотрудники WHERE Активен = 1
UNION ALL
SELECT ID, Имя, 'Неактивен' FROM Сотрудники WHERE Активен = 0
ORDER BY Статус, Имя;ID | Имя | Статус ---|---------|--------- 3 | Алексей | Активен 7 | Мария | Активен 5 | Игорь | Неактивен
Объединение результатов запросов с разными условиями фильтрации в одной таблице:
SELECT 'Высокий' AS Приоритет, COUNT(*) AS Количество FROM Заказы WHERE Сумма > 10000
UNION ALL
SELECT 'Средний', COUNT(*) FROM Заказы WHERE Сумма BETWEEN 5000 AND 10000
UNION ALL
SELECT 'Низкий', COUNT(*) FROM Заказы WHERE Сумма < 5000;