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

Когда стоит использовать объединение запросов в 1С?

2.0 Middle🔥 111 комментариев
#Запросы и оптимизация

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

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

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

Объединение запросов (UNION) в 1С: когда и зачем

Объединение запросов (UNION) — это операция, которая комбинирует результаты нескольких SELECT запросов в один набор результатов. Это мощный инструмент для специфических случаев работы с данными.

Что такое UNION?

UNION — это оператор SQL, который объединяет результаты двух или более запросов:

Запрос = Новый Запрос(
    "ВЫБРАТЬ
    |   Ссылка,
    |   Номер,
    |   Дата,
    |   Счёт Как ТипДокумента
    |ИЗ
    |   Документ.СчётФактура
    |
    |ОБЪЕДИНИТЬ
    |
    |ВЫБРАТЬ
    |   Ссылка,
    |   Номер,
    |   Дата,
    |   Накладная Как ТипДокумента
    |ИЗ
    |   Документ.Накладная
"
);

Результат = Запрос.Выполнить();

Этот запрос вернёт ВСЕ счета И ВСЕ накладные в одном наборе.

Две разновидности UNION

1. UNION (исключает дубликаты)

// UNION автоматически удаляет дубликаты
Запрос = Новый Запрос(
    "ВЫБРАТЬ
    |   Товар
    |ИЗ
    |   ТаблицаЗначений
    |
    |ОБЪЕДИНИТЬ
    |
    |ВЫБРАТЬ
    |   Товар
    |ИЗ
    |   ДругаяТаблица"
);

// Если в обеих таблицах есть одинаковый Товар,
// он выведется только один раз

2. UNION ALL (включает дубликаты)

// UNION ALL сохраняет все строки, даже дубликаты
Запрос = Новый Запрос(
    "ВЫБРАТЬ
    |   Товар
    |ИЗ
    |   ТаблицаЗначений
    |
    |ОБЪЕДИНИТЬ ВСЕ
    |
    |ВЫБРАТЬ
    |   Товар
    |ИЗ
    |   ДругаяТаблица"
);

// Дубликаты будут выведены столько раз, сколько они встречаются

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

1. Объединение однотипных документов

История всех движений товара из разных документов:

Запрос = Новый Запрос(
    "ВЫБРАТЬ
    |   ПриходОрдер.Дата,
    |   ПриходОрдер.Номер,
    |   ПриходОрдер.Товар,
    |   ПриходОрдер.Количество,
    |   Приход Как ТипДокумента
    |ИЗ
    |   Документ.ПриходОрдер Как ПриходОрдер
    |ГДЕ
    |   ПриходОрдер.Дата >= &ДатаНачала
    |
    |ОБЪЕДИНИТЬ ВСЕ
    |
    |ВЫБРАТЬ
    |   РасходОрдер.Дата,
    |   РасходОрдер.Номер,
    |   РасходОрдер.Товар,
    |   -РасходОрдер.Количество, -- Минус для расхода
    |   Расход Как ТипДокумента
    |ИЗ
    |   Документ.РасходОрдер Как РасходОрдер
    |ГДЕ
    |   РасходОрдер.Дата >= &ДатаНачала
    |
    |ПОРЯДОК ПО
    |   Дата, ТипДокумента"
);
Запрос.УстановитьПараметр("ДатаНачала", 20240101);

Результат = Запрос.Выполнить();

2. Получение всех контактов из разных источников

Объединение контактов сотрудников и контрагентов:

Запрос = Новый Запрос(
    "ВЫБРАТЬ
    |   Сотрудники.ФИО,
    |   Сотрудники.Телефон,
    |   Сотрудник Как ТипКонтакта
    |ИЗ
    |   Справочник.Сотрудники Как Сотрудники
    |ГДЕ
    |   НЕ Сотрудники.ПометкаУдаления
    |
    |ОБЪЕДИНИТЬ
    |
    |ВЫБРАТЬ
    |   Контрагенты.Наименование,
    |   Контрагенты.Телефон,
    |   Контрагент Как ТипКонтакта
    |ИЗ
    |   Справочник.Контрагенты Как Контрагенты
    |ГДЕ
    |   НЕ Контрагенты.ПометкаУдаления
    |
    |ПОРЯДОК ПО
    |   1 -- Сортировка по ФИО/Наименованию"
);

3. Статистика из разных регистров

Объединение данных из остатков и оборотов:

Запрос = Новый Запрос(
    "ВЫБРАТЬ
    |   ОстаткиТоваров.Товар,
    |   ОстаткиТоваров.Количество,
    |   Остаток Как ТипДанных
    |ИЗ
    |   РегистрНакопления.ОстаткиТоваров.Остатки(&Дата, ) Как ОстаткиТоваров
    |
    |ОБЪЕДИНИТЬ
    |
    |ВЫБРАТЬ
    |   ОборотыТоваров.Товар,
    |   ОборотыТоваров.ОборотПриход,
    |   Приход Как ТипДанных
    |ИЗ
    |   РегистрНакопления.ОстаткиТоваров.Обороты(&ДатаНачала, &ДатаОкончания) Как ОборотыТоваров"
);
Запрос.УстановитьПараметр("Дата", ТекущаяДата());
Запрос.УстановитьПараметр("ДатаНачала", НачалоМесяца(ТекущаяДата()));
Запрос.УстановитьПараметр("ДатаОкончания", КонецМесяца(ТекущаяДата()));

Ограничения и требования UNION

Важные правила:

// ✅ ПРАВИЛЬНО: одинаковое количество колонок и совместимые типы
ВЫБРАТЬ
    Номер,           -- Строка
    Дата,            -- Дата
    Сумма            -- Число
ИЗ Документ.СчётФактура

ОБЪЕДИНИТЬ

ВЫБРАТЬ
    Номер,           -- Строка
    Дата,            -- Дата
    Сумма            -- Число (совместимый тип)
ИЗ Документ.Накладная

// ❌ НЕПРАВИЛЬНО: разное количество колонок
ВЫБРАТЬ
    Номер,
    Дата
ИЗ Документ.СчётФактура

ОБЪЕДИНИТЬ

ВЫБРАТЬ
    Номер,
    Дата,
    Сумма            -- ОШИБКА! Разное количество колонок
ИЗ Документ.Накладная

// ❌ НЕПРАВИЛЬНО: несовместимые типы
ВЫБРАТЬ
    Номер,           -- Строка
    Дата             -- Дата
ИЗ Документ.СчётФактура

ОБЪЕДИНИТЬ

ВЫБРАТЬ
    Номер,           -- Строка (OK)
    Контрагент       -- Ссылка (НЕСОВМЕСТИМО с Датой!)
ИЗ Документ.Накладная

Практический пример: Реестр всех операций

Процедура ПолучитьРеестрОперацийПоДате(ДатаНачала, ДатаОкончания)
    Запрос = Новый Запрос(
        "ВЫБРАТЬ
        |   Счета.Дата,
        |   Счета.Номер,
        |   Счёт Как ТипОперации,
        |   Счета.Контрагент.Наименование Как Контрагент,
        |   Счета.Сумма,
        |   Счета.Ссылка
        |ИЗ
        |   Документ.СчётФактура Как Счета
        |ГДЕ
        |   Счета.Дата >= &ДатаНачала
        |   И Счета.Дата <= &ДатаОкончания
        |
        |ОБЪЕДИНИТЬ ВСЕ
        |
        |ВЫБРАТЬ
        |   Накладные.Дата,
        |   Накладные.Номер,
        |   Накладная Как ТипОперации,
        |   Накладные.Контрагент.Наименование,
        |   Накладные.Сумма,
        |   Накладные.Ссылка
        |ИЗ
        |   Документ.Накладная Как Накладные
        |ГДЕ
        |   Накладные.Дата >= &ДатаНачала
        |   И Накладные.Дата <= &ДатаОкончания
        |
        |ОБЪЕДИНИТЬ ВСЕ
        |
        |ВЫБРАТЬ
        |   Платежи.Дата,
        |   Платежи.Номер,
        |   Платёж Как ТипОперации,
        |   Платежи.Контрагент.Наименование,
        |   Платежи.Сумма,
        |   Платежи.Ссылка
        |ИЗ
        |   Документ.ПлатёжПоДорого Как Платежи
        |ГДЕ
        |   Платежи.Дата >= &ДатаНачала
        |   И Платежи.Дата <= &ДатаОкончания
        |
        |ПОРЯДОК ПО
        |   Дата УБЫВ,
        |   ТипОперации"
    );
    
    Запрос.УстановитьПараметр("ДатаНачала", ДатаНачала);
    Запрос.УстановитьПараметр("ДатаОкончания", ДатаОкончания);
    
    Результат = Запрос.Выполнить().Выбрать();
    
    Пока Результат.Следующий() Цикл
        Сообщение(
            Результат.Дата + " | " +
            Результат.ТипОперации + " № " + Результат.Номер + " | " +
            Результат.Контрагент + " | " +
            Результат.Сумма
        );
    КонецЦикла;
КонецПроцедуры

UNION vs LEFT JOIN: различия

АспектUNIONLEFT JOIN
НазначениеКомбинирует результаты нескольких запросовОбъединяет две таблицы по условию
РезультатВертикальное объединение (строки добавляются)Горизонтальное объединение (колонки добавляются)
СтруктураОдинаковое количество колонокМожет быть разное
ПроизводительностьХороша для небольших выборокЛучше для больших объёмов
Типичный случайИстория из разных источниковСвязь одной таблицы с другой

Производительность UNION

Рекомендации:

  1. Используй UNION ALL вместо UNION — если дубликаты неважны (UNION ALL быстрее)
  2. Ограничивай результаты — добавляй WHERE для сужения выборки
  3. Индексируй колонки — на которых есть условия WHERE
  4. Избегай сложных трансформаций — в UNION запросах
// ✅ ХОРОШО: простой UNION ALL с фильтрацией
ВЫБРАТЬ
    Дата, Номер, Сумма
ИЗ Документ.СчётФактура
ГДЕ Дата >= &ДатаНачала

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    Дата, Номер, Сумма
ИЗ Документ.Накладная
ГДЕ Дата >= &ДатаНачала

// ❌ ПЛОХО: сложные трансформации в UNION
ВЫБРАТЬ
    ДобавитьМесяц(Дата, 1),
    ПОДСТРОКА(Номер, 1, 5),
    Сумма * (1 + НДС)
ИЗ Документ.СчётФактура

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    ...

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

  1. Если нужно объединить две таблицы на основе ключа — используй JOIN
  2. Если нужны разные колонки из разных таблиц — используй LEFT JOIN
  3. Если нужна агрегация — используй GROUP BY
  4. Если данные очень большого объёма — рассмотри индексы и оптимизацию

Объединение запросов (UNION) — это элегантный способ комбинирования данных из разных источников при условии, что структура результатов совпадает.