Урок курса

UNION и UNION ALL

SQL с нуля: бесплатный курс с практикой

До сих пор каждый запрос работал с одной таблицей или соединял несколько через JOIN — то есть расширял строки по горизонтали, добавляя столбцы из связанных таблиц. UNION делает противоположное: берёт результаты двух отдельных SELECT и склеивает их по вертикали, добавляя строки снизу.

UNION: синтаксис склейки двух SELECT, требования к столбцам и удаление дубликатов

Представьте две таблицы: offices с городами офисов и warehouses с городами складов. Нужен единый список всех городов присутствия. JOIN здесь не поможет — между таблицами нет смыслового ключа для соединения. Именно для этого существует UNION.

Базовый синтаксис:

SELECT city FROM offices
UNION
SELECT city FROM warehouses;

SQLite выполнит оба SELECT, соберёт все строки в один промежуточный набор и вернёт результат как единую таблицу. Имена столбцов в итоге — из первого SELECT. Если нужен конкретный заголовок, псевдоним ставится тоже в первом запросе:

SELECT city AS location FROM offices
UNION
SELECT city FROM warehouses;

Второй AS здесь игнорируется — заголовок всегда определяет первый SELECT.

У UNION есть одно строгое синтаксическое требование: оба SELECT должны возвращать одинаковое число столбцов. Соответствующие позиции также должны иметь совместимый смысл и типы — это правило переносимого SQL и нормальной модели данных. SQLite из-за динамической типизации может выполнить объединение со значениями разных типов в одной позиции, но полагаться на это не стоит; для явного результата используйте CAST.

Если нарушить первое условие — например, в одном SELECT два столбца, а в другом три — база вернёт ошибку вида each UNION query must have the same number of columns. Исправление простое: выровнять число столбцов, добавив константу или NULL как заглушку:

SELECT city, region FROM offices
UNION
SELECT city, NULL FROM warehouses;

Теперь о главном поведении UNION — удалении дубликатов. После склейки UNION проходит по всему набору строк и выбрасывает те, которые полностью совпадают по значениям всех столбцов. Это работает аналогично SELECT DISTINCT, только применяется ко всему результату объединения. Если «Казань» есть и в offices, и в warehouses, в итоговом результате она появится ровно один раз.

Механизм дедупликации требует дополнительной работы от СУБД: она должна сравнить каждую строку с уже виденными. На больших объёмах это заметно сказывается на скорости. Когда дубликаты в результате нежелательны и данные с перекрытием — UNION оправдан. Когда нужна максимальная скорость или дубликаты важны, это уже другой инструмент — о нём в следующей секции.

Сравнение UNION, который удаляет повторяющуюся Москву, и UNION ALL, который сохраняет обе одинаковые строки
UNION и UNION ALL различаются обработкой дубликатов

UNION ALL: сохранение всех строк и наблюдаемая разница в количестве строк

Создадим учебную базу из примера и сравним оба варианта в цифрах:

CREATE TABLE offices (city TEXT);
INSERT INTO offices VALUES ('Москва'), ('Казань'), ('Самара');

CREATE TABLE warehouses (city TEXT);
INSERT INTO warehouses VALUES ('Казань'), ('Уфа');

Теперь два запроса на одних и тех же данных:

-- Вариант 1
SELECT city FROM offices
UNION
SELECT city FROM warehouses;

-- Вариант 2
SELECT city FROM offices
UNION ALL
SELECT city FROM warehouses;

Первый вернёт 4 строки: Москва, Казань, Самара, Уфа — «Казань» из warehouses отброшена как дубликат. Второй вернёт 5 строк: те же четыре плюс вторую «Казань». UNION ALL не делает никакой проверки — он просто дописывает строки второго SELECT снизу к строкам первого. Если в первом запросе N строк, а во втором M, результат UNION ALL содержит ровно N + M строк, без исключений.

Чтобы увидеть разницу числом, достаточно обернуть оба запроса в COUNT(*):

SELECT COUNT(*) FROM (
    SELECT city FROM offices
    UNION
    SELECT city FROM warehouses
);
-- результат: 4

SELECT COUNT(*) FROM (
    SELECT city FROM offices
    UNION ALL
    SELECT city FROM warehouses
);
-- результат: 5

Разница в одну строку — это именно «Казань», которую UNION обнаружил и убрал при сравнении со строкой из первого SELECT.

Когда стоит выбирать UNION ALL? Во-первых, когда дубликаты несут смысл — например, нужно подсчитать, сколько раз один и тот же город встречается в обеих таблицах. Во-вторых, когда данные заведомо не пересекаются и тратить время на дедупликацию бессмысленно. В-третьих, когда объём большой и производительность важна: UNION ALL не строит временный набор для сравнения строк, он просто конкатенирует результаты.

Практическое правило: пишите UNION ALL по умолчанию, если точно знаете структуру данных. Переключайтесь на UNION, когда нужна гарантия уникальности строк в результате и готовы заплатить за неё скоростью.

Задача 1

table_a содержит 6 различных значений col, table_b — 4 различных значения col. Ровно 3 значения встречаются в обоих результатах; других совпадений нет. Сколько строк вернут два запроса?

Запрос 1: SELECT col FROM table_a UNION ALL SELECT col FROM table_b;
Запрос 2: SELECT col FROM table_a UNION SELECT col FROM table_b;

Выберите один вариант
Без регистрации · результат не сохраняется

Задача 2

Аналитик пишет запрос:

SELECT name FROM clients UNION SELECT name, email FROM suppliers;

Что произойдёт при выполнении этого запроса?

Выберите один вариант
Без регистрации · результат не сохраняется

Задача 3

В каком SELECT нужно задать псевдоним AS, чтобы изменить заголовок столбца в результате UNION? Введите только номер: 1 или 2.

Без регистрации · результат не сохраняется

Задача 4

Все города из двух источников

Есть две таблицы с одним столбцом: online_customers(city) и store_customers(city). Напишите один запрос, который возвращает один столбец city со всеми строками обоих источников, включая повторяющиеся города. Используйте UNION ALL, а не UNION, и отсортируйте итоговый результат по city по возрастанию.

РешениеSQL · SQLite

Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.

Отправьте решение, чтобы увидеть результаты тестов.

Задачи к уроку

Все задачи курса →

Продолжить с сохранением прогресса

Перейдите к уроку в учебном кабинете.

Перейти к интерактивному уроку