Как правильно использовать ОБЪЕДИНИТЬ и ОБЪЕДИНИТЬ ВСЕ в одном запросе 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При построении сложных отчетов и выборок в 1С нередко возникает необходимость объединить несколько наборов данных. Иногда требуется объединить две выборки без удаления дублей, а затем полученный результат объединить с другой группой выборок, но уже с исключением повторяющихся строк. Разберем, как именно платформа 1С обрабатывает конструкции ОБЪЕДИНИТЬ и ОБЪЕДИНИТЬ ВСЕ, какие существуют ограничения и как правильно управлять порядком их выполнения.

Порядок выполнения операторов объединения в 1С

В языке запросов 1С, как и в стандарте SQL, операторы ОБЪЕДИНИТЬ и ОБЪЕДИНИТЬ ВСЕ обладают абсолютно одинаковым приоритетом. Запрос выполняется строго последовательно сверху вниз (по правилу левой ассоциативности).

Рассмотрим распространенное заблуждение: попытку написать единое полотно запроса с расчетом на то, что центральный оператор ОБЪЕДИНИТЬ сгруппирует два независимых блока, соединенных через ОБЪЕДИНИТЬ ВСЕ.

Проанализируем практический пример, показывающий, как на самом деле вычисляются подобные цепочки:


ВЫБРАТЬ
    1 КАК Значение
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
    1
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
    1
ОБЪЕДИНИТЬ 
ВЫБРАТЬ
    1

В данном случае сначала накапливаются три единицы через ОБЪЕДИНИТЬ ВСЕ, а затем оператор ОБЪЕДИНИТЬ сравнивает полученный набор (три единицы) со следующей выборкой (одна единица) и исключает все дубликаты. Результат выполнения такого запроса — 1 строка со значением 1.

Посмотрим на другой пример изменения позиции оператора:


ВЫБРАТЬ
    1 КАК Значение
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
    1
ОБЪЕДИНИТЬ 
ВЫБРАТЬ
    1
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
    1

Разберем по шагам, что происходит в этом запросе:

  1. Первые две выборки соединяются через ОБЪЕДИНИТЬ ВСЕ (получаем 2 строки).
  2. Следующее ОБЪЕДИНИТЬ схлопывает накопленные строки со значением 1 из третьей выборки (остается 1 строка).
  3. Последний оператор ОБЪЕДИНИТЬ ВСЕ просто добавляет строку из четвертой выборки.
  4. Итоговый результат — 2 строки.

Синтаксис 1С не поддерживает выделение блоков объединения обычными круглыми скобками вида (Запрос1 ОБЪЕДИНИТЬ ВСЕ Запрос2) ОБЪЕДИНИТЬ (Запрос3 ОБЪЕДИНИТЬ ВСЕ Запрос4). Чтобы задать явную иерархию и порядок обработки, необходимо использовать другие архитектурные приемы.

Способ 1. Использование вложенных запросов

Если требуется сформировать два независимых составных набора данных, внутри каждого из которых сохраняются дубли, а затем исключить одинаковые строки между этими блоками, применяются вложенные запросы в секции ИЗ.

Рассмотрим структуру такого запроса:


ВЫБРАТЬ
    Вложенный1.Поле1 КАК Поле1,
    Вложенный1.Поле2 КАК Поле2
ИЗ
    (ВЫБРАТЬ
        Таблица1.Поле1 КАК Поле1,
        Таблица1.Поле2 КАК Поле2
    ИЗ
        Справочник.Номенклатура КАК Таблица1
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
        Таблица2.Поле1,
        Таблица2.Поле2
    ИЗ
        Справочник.Номенклатура КАК Таблица2) КАК Вложенный1

ОБЪЕДИНИТЬ

ВЫБРАТЬ
    Вложенный2.Поле1,
    Вложенный2.Поле2
ИЗ
    (ВЫБРАТЬ
        Таблица3.Поле1 КАК Поле1,
        Таблица3.Поле2 КАК Поле2
    ИЗ
        Справочник.Номенклатура КАК Таблица3
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
        Таблица4.Поле1,
        Таблица4.Поле2
    ИЗ
        Справочник.Номенклатура КАК Таблица4) КАК Вложенный2

Такой подход изолирует внутренние объединения от финального оператора ОБЪЕДИНИТЬ, гарантируя ожидаемый порядок выполнения.

Способ 2. Использование временных таблиц

В сложных запросах с большим количеством полей и условий предпочтительным вариантом является разделение логики с помощью временных таблиц. Это повышает читаемость кода и упрощает его отладку.

Посмотрим на пример с помещением промежуточных блоков во временную таблицу:


ВЫБРАТЬ
    Таблица1.Номенклатура КАК Номенклатура,
    Таблица1.Количество КАК Количество
ПОМЕСТИТЬ ВТ_ПервыйБлок
ИЗ
    Документ.РеализацияТоваровУслуг.Товары КАК Таблица1

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

ВЫБРАТЬ
    Таблица2.Номенклатура,
    Таблица2.Количество
ИЗ
    Документ.ПоступлениеТоваровУслуг.Товары КАК Таблица2
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Таблица3.Номенклатура КАК Номенклатура,
    Таблица3.Количество КАК Количество
ПОМЕСТИТЬ ВТ_ВторойБлок
ИЗ
    Документ.ПеремещениеТоваров.Товары КАК Таблица3

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

ВЫБРАТЬ
    Таблица4.Номенклатура,
    Таблица4.Количество
ИЗ
    Документ.ОприходованиеТоваров.Товары КАК Таблица4
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ1.Номенклатура,
    ВТ1.Количество
ИЗ
    ВТ_ПервыйБлок КАК ВТ1

ОБЪЕДИНИТЬ

ВЫБРАТЬ
    ВТ2.Номенклатура,
    ВТ2.Количество
ИЗ
    ВТ_ВторойБлок КАК ВТ2

Ограничения и рекомендации по оптимизации

При использовании оператора ОБЪЕДИНИТЬ (без слова ВСЕ) важно учитывать особенности работы платформы и СУБД:

  1. Поля неограниченной длины: Оператор ОБЪЕДИНИТЬ выполняет неявную операцию дедупликации (сортировку и группировку на стороне СУБД). Если в выборке присутствуют поля с типом Строка неограниченной длины или ХранилищеЗначения, возникнет ошибка. Для таких полей необходимо явно задавать длину через функцию ВЫРАЗИТЬ(Поле КАК Строка(100)).
  2. Производительность: Неявное исключение дубликатов создает повышенную нагрузку на сервер баз данных. В стандартах разработки 1С рекомендуется отдавать предпочтение конструкции ОБЪЕДИНИТЬ ВСЕ, а схлопывание строк реализовывать явно через СГРУППИРОВАТЬ ПО с применением агрегатных функций (СУММА, МАКСИМУМ) во внешнем запросе.
← На главную