Как в запросе 1С добавить строки из второй таблицы, если первая не пустая?

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

В процессе работы с запросами в 1С часто возникают задачи, которые не решаются стандартными операторами. В таких ситуациях разработчику полезно иметь под рукой шпаргалку по языку запросов. Одна из таких задач — необходимость добавить (объединить) данные из второй таблицы к первой только при выполнении определенного условия: если первая таблица содержит хотя бы одну запись. Если же первая таблица пуста, итоговый результат тоже должен быть пустым.

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

Правильным и наиболее эффективным подходом для реализации такой условной логики в языке запросов 1С является использование пакетных запросов и временных таблиц. Для отладки подобных конструкций идеально подходит консоль запросов с полной поддержкой пакетных запросов и временных таблиц. Проанализируем этот метод по шагам.

Основная идея решения: пакетный запрос и временная таблица

Суть метода заключается в том, чтобы разбить нашу задачу на несколько последовательных шагов (пакетов):

  1. Пакет 1: Выполняем основной запрос к первой таблице и сохраняем его результат во временную таблицу. Это наш "якорь" и основа для условия.
  2. Пакет 2: Формируем итоговый результат. Мы выбираем все данные из созданной временной таблицы и через ОБЪЕДИНИТЬ ВСЕ добавляем данные из второй таблицы. Но вторая выборка выполняется с хитрым условием в секции ГДЕ, которое проверяет, есть ли записи в нашей временной таблице.

Такой подход гарантирует, что если в первом пакете ничего не будет выбрано, временная таблица останется пустой, и во втором пакете условие для объединения не выполнится, что приведет к пустому итоговому результату. При проектировании сложных схем можно также использовать консоль запросов для управляемых форм, которая поддерживает редактор объектов и логи ТЖ.

Разберем по шагам на примере

Рассмотрим исходную задачу. У нас есть две таблицы:

Нам нужно получить итоговую таблицу со структурой ТаблицыА, в которую будут добавлены данные из ТаблицыБ (с сопоставлением полей и заполнением недостающих данных константами), но только если ТаблицаА не пустая.

Шаг 1. Формирование основной выборки и помещение во временную таблицу

Первым делом создадим временную таблицу, в которую поместим результат запроса к ТаблицеА. Назовем ее ВТ_ОсновнаяТаблица. Стоит отметить, что в современных версиях платформы появилось добавление данных в существующую временную таблицу, но в данном примере мы создаем таблицу "с нуля" в первом пакете запроса.


// -- Пакет 1: Создание временной таблицы с основными данными --
ВЫБРАТЬ
    Т1.Ответственный,
    Т1.Подразделение,
    Т1.Выручка
ПОМЕСТИТЬ ВТ_ОсновнаяТаблица
ИЗ
    ТаблицаА КАК Т1
ГДЕ
    // Здесь могут быть ваши условия отбора для основной таблицы
; // <-- Важный момент: разделитель пакетов

После выполнения этого пакета у нас есть временная таблица ВТ_ОсновнаяТаблица, которая либо содержит данные, либо пуста, в зависимости от результатов выборки из ТаблицаА.

Шаг 2. Финальная выборка с условным объединением

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

Запрос будет состоять из двух частей, соединенных через ОБЪЕДИНИТЬ ВСЕ.

Первая часть — простая выборка всех данных из нашей временной таблицы. Если она пуста, эта часть запроса ничего не вернет.


ВЫБРАТЬ
    Ответственный,
    Подразделение,
    Выручка
ИЗ
    ВТ_ОсновнаяТаблица

Вторая часть — это выборка из ТаблицаБ. И здесь кроется главный секрет. Мы добавляем условие ГДЕ, которое проверяет наличие записей во временной таблице ВТ_ОсновнаяТаблица с помощью вложенного запроса.


ВЫБРАТЬ
    Т2.Ассистент КАК Ответственный,
    NULL КАК Подразделение, // Заполняем недостающие поля константами или NULL
    0 КАК Выручка
ИЗ
    ТаблицаБ КАК Т2
ГДЕ
    // Вот то самое условие!
    (ВЫБРАТЬ КОЛИЧЕСТВО(1) ИЗ ВТ_ОсновнаяТаблица) > 0

Рассмотрим подробнее ключевую конструкцию: (ВЫБРАТЬ КОЛИЧЕСТВО(1) ИЗ ВТ_ОсновнаяТаблица) > 0.

Обратите внимание, что мы приводим структуру выборки из ТаблицаБ к структуре ТаблицаА, используя псевдонимы полей (КАК Ответственный) и заполняя недостающие поля (Подразделение, Выручка) значениями по умолчанию, например NULL или 0.

Итоговый пакетный запрос

Теперь соберем все части вместе. Полный пакетный запрос будет выглядеть так:


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

// -- Пакет 2: Финальная выборка с условным объединением --
ВЫБРАТЬ
    Ответственный,
    Подразделение,
    Выручка
ИЗ
    ВТ_ОсновнаяТаблица

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

ВЫБРАТЬ
    Т2.Ассистент,
    NULL, // Или "ПодразделениеПоУмолчанию"
    0 // Константное значение для выручки
ИЗ
    ТаблицаБ КАК Т2
ГДЕ
    // Условие, которое выполнится, только если первая таблица не пустая
    (ВЫБРАТЬ КОЛИЧЕСТВО(1) ИЗ ВТ_ОсновнаяТаблица) > 0

Анализ работы запроса в двух сценариях

Сценарий 1: ТаблицаА содержит данные.

  1. Пакет 1 выполняется, и ВТ_ОсновнаяТаблица заполняется записями.
  2. В Пакете 2 первая часть ОБЪЕДИНИТЬ ВСЕ выбирает все записи из ВТ_ОсновнаяТаблица.
  3. Вложенный запрос (ВЫБРАТЬ КОЛИЧЕСТВО(1) ...) возвращает число больше 0. Условие в ГДЕ истинно.
  4. Вторая часть ОБЪЕДИНИТЬ ВСЕ выбирает данные из ТаблицаБ.
  5. Результат: Итоговая таблица содержит записи из ТаблицаА и ТаблицаБ. Задача выполнена.

Сценарий 2: ТаблицаА пуста.

  1. Пакет 1 выполняется, но не находит ни одной записи. ВТ_ОсновнаяТаблица создается, но остается пустой.
  2. В Пакете 2 первая часть ОБЪЕДИНИТЬ ВСЕ пытается выбрать данные из пустой ВТ_ОсновнаяТаблица и возвращает пустой результат.
  3. Вложенный запрос (ВЫБРАТЬ КОЛИЧЕСТВО(1) ...) возвращает 0. Условие 0 > 0 ложно.
  4. Вторая часть ОБЪЕДИНИТЬ ВСЕ из-за ложного условия в ГДЕ также возвращает пустой результат.
  5. Результат: Итоговая таблица пуста, что и требовалось.

Таким образом, использование связки пакетного запроса, временной таблицы и вложенного запроса в условии ГДЕ позволяет элегантно и эффективно решать задачи с условной логикой, которые невозможно или очень сложно реализовать в рамках одного простого запроса.

← На главную