Kitabı oxu: «UNION в SQL. 18 задач на объединение таблиц»

Şrift:

Перед первой задачей

Зачем нужен UNION

UNION нужен, когда данные лежат в нескольких похожих таблицах или запросах, а в отчёте нужна одна общая лента строк.

Типичная ситуация: продажи за разные периоды, клиенты из разных источников, события сайта и приложения, старый и новый справочник.

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

Как не сломать объединение

У всех частей UNION должно быть одинаковое количество колонок в одинаковом порядке. Названия важны для читаемости, но структура важнее.

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

Перед объединением полезно добавить колонку source. Тогда после UNION ALL видно, откуда пришла каждая строка.

Маршрут по задачам

1. Собрать клиентов из двух таблиц

2. Сохранить повторы через UNION ALL

3. Добавить источник каждой строки

4. Объединить старые и новые заказы

5. Собрать общий справочник категорий

6. Объединить события сайта и приложения

7. Посчитать строки после UNION ALL

8. Посчитать уникальные значения после UNION

9. Совместить разные названия колонок

10. Добавить пустую колонку для совместимости

11. Отфильтровать каждую часть перед объединением

12. Агрегировать общий поток

13. Объединить разные типы событий

14. Найти пересечение через UNION ALL и GROUP BY

15. Найти строки только из одного списка

16. Собрать отчёт с источником периода

17. Проверить совместимость типов

18. Собрать финальный отчёт из трёх потоков

Практические задачи

Задача 1. Собрать клиентов из двух таблиц

Рабочий вопрос

Нужно получить общий список email из двух источников клиентов и убрать повторяющиеся адреса.

Данные

CREATE TABLE buyers_2025(email TEXT);

CREATE TABLE buyers_2026(email TEXT);

INSERT INTO buyers_2025 VALUES ('anna@example.test'),('oleg@example.test');

INSERT INTO buyers_2026 VALUES ('oleg@example.test'),('nina@example.test');

Запрос

SELECT email FROM buyers_2025

UNION

SELECT email FROM buyers_2026

ORDER BY email;

Ожидаемый результат

[["anna@example.test"], ["nina@example.test"], ["oleg@example.test"]]

Почему работает

UNION объединяет строки из двух SELECT.

Повтор oleg@example.test остаётся один раз.

ORDER BY в конце сортирует уже общий результат.

Где легко ошибиться

UNION удаляет дубли. Если повторная покупка важна как отдельный факт, такой запрос может занизить количество событий.

Самостоятельная проверка

Почему oleg@example.test показан один раз, хотя есть в обеих исходных таблицах?

Ответ: Потому что UNION возвращает уникальные строки общего результата.

Задача 2. Сохранить повторы через UNION ALL

Рабочий вопрос

Нужно объединить продажи двух дней и сохранить каждую строку, даже если суммы совпадают.

Данные

CREATE TABLE sales_day1(id INTEGER, total INTEGER);

CREATE TABLE sales_day2(id INTEGER, total INTEGER);

INSERT INTO sales_day1 VALUES (1,500),(2,300);

INSERT INTO sales_day2 VALUES (3,500),(4,200);

Запрос

SELECT total FROM sales_day1

UNION ALL

SELECT total FROM sales_day2

ORDER BY total DESC;

Ожидаемый результат

[[500], [500], [300], [200]]

Почему работает

UNION ALL не удаляет одинаковые строки.

Две продажи на 500 остаются двумя строками.

Сортировка выполняется после объединения двух дней.

Где легко ошибиться

Если заменить UNION ALL на UNION, одна из одинаковых сумм 500 исчезнет из результата.

Самостоятельная проверка

Почему для отчёта по фактам продаж UNION ALL безопаснее, чем UNION?

Ответ: Факты продаж могут иметь одинаковые значения, и их нельзя удалять как дубли без отдельного правила.

Задача 3. Добавить источник каждой строки

Рабочий вопрос

Нужно объединить лиды из сайта и формы, сохранив колонку, которая показывает исходный канал.

Данные

CREATE TABLE site_leads(email TEXT);

CREATE TABLE form_leads(email TEXT);

INSERT INTO site_leads VALUES ('a@example.test'),('b@example.test');

INSERT INTO form_leads VALUES ('b@example.test'),('c@example.test');

Запрос

SELECT 'site' AS source, email FROM site_leads

UNION ALL

SELECT 'form' AS source, email FROM form_leads

ORDER BY email, source;

Ожидаемый результат

[["site", "a@example.test"], ["form", "b@example.test"], ["site", "b@example.test"], ["form", "c@example.test"]]

Почему работает

Каждый SELECT добавляет постоянную колонку source.

UNION ALL сохраняет одинаковый email из разных каналов.

После объединения видно, откуда пришла каждая строка.

Где легко ошибиться

Без source одинаковый email из разных каналов трудно разобрать после объединения.

Самостоятельная проверка

Почему b@example.test остался двумя строками в результате?

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

Задача 4. Объединить старые и новые заказы

Рабочий вопрос

Нужно построить единый список заказов после миграции, когда часть данных лежит в старой таблице, а часть в новой.

Данные

CREATE TABLE old_orders(id INTEGER, created_at TEXT, total INTEGER);

CREATE TABLE new_orders(id INTEGER, created_at TEXT, total INTEGER);

INSERT INTO old_orders VALUES (1,'2026-08-30',300),(2,'2026-08-31',500);

INSERT INTO new_orders VALUES (3,'2026-09-01',700),(4,'2026-09-02',200);

Запрос

SELECT id, created_at, total FROM old_orders

UNION ALL

SELECT id, created_at, total FROM new_orders

ORDER BY created_at, id;

Ожидаемый результат

[[1, "2026-08-30", 300], [2, "2026-08-31", 500], [3, "2026-09-01", 700], [4, "2026-09-02", 200]]

Почему работает

Обе таблицы имеют одинаковые колонки.

UNION ALL сохраняет все четыре заказа.

ORDER BY created_at собирает общий календарный порядок.

Где легко ошибиться

Если порядок колонок в двух SELECT отличается, SQL выполнится, но значения попадут не в тот смысловой столбец.

Самостоятельная проверка

Почему в обоих SELECT важно писать колонки в одном порядке?

Ответ: UNION сопоставляет колонки по позиции, а не по их исходным именам в таблицах.

Pulsuz fraqment bitdi.