В отчёте объединяют текущие и архивные данные, причём одинаковая строка может находиться в обеих таблицах. Как выбрать оператор, чтобы сохранить оба вхождения?
Используйте UNION ALL: он сохраняет каждую строку каждого источника, включая полностью одинаковые строки. Обычный UNION перед возвратом результата устраняет дубликаты, рассматривая строки как набор значений выбранных столбцов.
Реляционная модель рассматривает результат объединения как множество, где одинаковые элементы присутствуют один раз. В практическом SQL результаты запросов обычно поддерживают повторяющиеся строки, поэтому появились два варианта: UNION для поведения с устранением дублей и UNION ALL для сохранения кратности.
Такое разделение позволяет явно выбрать между логикой множества и логикой мультимножества. Устранение дублей требует дополнительной обработки результата, поэтому сохранение строк через UNION ALL обычно проще и эффективнее.
Обычный UNION сравнивает не исходные строки и не их идентификаторы, а значения всех столбцов, выбранных в соответствующих позициях. Поэтому он может ошибочно объединить две разные бизнес-записи, если после проекции их значения совпали.
Например, архивная и текущая строки с одинаковыми идентификатором, суммой и датой будут представлены одной строкой при UNION. Это приводит к занижению количества записей и может исказить агрегаты, если ожидается учёт каждого физического вхождения.
Для сохранения всех строк применяют UNION ALL. Количество строк результата равно сумме количества строк обоих запросов, включая повторяющиеся значения.
Для обычного UNION результат сначала формируется из обоих запросов, затем одинаковые строки удаляются. Одинаковыми считаются строки, у которых совпадают значения всех возвращаемых столбцов; наличие одинакового идентификатора само по себе недостаточно, если остальные значения различаются.
У частей объединения должны быть совместимые по позициям количество и типы столбцов. Имена столбцов результата обычно берутся из первого запроса, поэтому структура и смысл проекции должны быть согласованы заранее.
Если нужно сохранить все вхождения, но затем убрать дубли по бизнес-ключу с заданным правилом выбора, простая замена на UNION недостаточна. Следует использовать UNION ALL, а дедупликацию выполнять явно: например, по ключу с выбором самой новой версии строки.
Порядок строк ни UNION, ни UNION ALL не гарантирует. Для определённого порядка нужен завершающий ORDER BY у всего объединённого результата, а не предположение о порядке чтения источников.
Система хранит закрытые заказы в архиве, но во время миграции часть заказов временно присутствует и в текущей, и в архивной таблице. Требование отчёта — показать каждое физическое вхождение и отдельно выявить дубли.
Вариант с UNION проще, но скрывает факт повторного присутствия: полностью совпавшие строки схлопываются. Вариант с UNION ALL сохраняет данные, однако отчёт может содержать дубли, если бизнес-правило требует показывать только одну версию заказа.
Выбран UNION ALL, потому что на первом этапе важно не терять факты загрузки. После объединения записи группируют или ранжируют по бизнес-ключу, а конфликтующие версии проверяют отдельно. Это сохраняет полноту исходных данных и не маскирует ошибки миграции.
1. Удаляет ли UNION дубли по идентификатору строки?
Нет. UNION сравнивает полные результирующие строки по значениям всех выбранных столбцов. Если два источника содержат одинаковый идентификатор, но разные сумму или статус, обе строки останутся в результате.
И наоборот, строки с разными исходными идентификаторами могут схлопнуться, если идентификатор не включён в проекцию и все выбранные значения совпадают. Поэтому дедупликацию по бизнес-ключу нужно задавать отдельно.
2. Сохранит ли UNION ALL две полностью одинаковые строки?
Да. UNION ALL не выполняет устранение дублей, поэтому каждая строка учитывается столько раз, сколько раз она получена из частей объединения.
Это особенно важно для агрегатов: последующий COUNT(*) посчитает оба вхождения. Если повторения являются ошибкой, их нужно удалять явным правилом, а не рассчитывать на случайное устранение.
3. Гарантирует ли UNION порядок строк из первого запроса, а затем из второго?
Нет. Результат объединения является неупорядоченным, если для него явно не задан ORDER BY. Оптимизатор может читать источники и объединять результаты в другом порядке.
Если порядок важен, добавляют сортировку к итоговому результату и включают в неё необходимые столбцы. Порядок строк внутри отдельных частей без завершающей сортировки также не является гарантией.