Как использовать результат запроса в качестве параметров виртуальной таблицы

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

В процессе разработки сложных отчетов или механизмов получения данных в 1С:Предприятии программисты часто сталкиваются с необходимостью передать данные, полученные в одном пакете запроса, в качестве параметров (таких как Дата, Организация или Подразделение) для виртуальной таблицы (например, Хозрасчетный.Остатки) в другом пакете. Рассмотрим подробнее, почему стандартный подход «в лоб» не работает и какие существуют архитектурно правильные решения этой задачи.

Анализ технического ограничения платформы 1С

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

Проанализируем ситуацию: платформа не может динамически менять срез данных для виртуальной таблицы в зависимости от строки другой таблицы внутри одного вызова Выполнить(). Таким образом, конструкция типа Хозрасчетный.Остатки(ВТ_Данные.НужнаяДата, ...) синтаксически невозможна.

Решение 1: Передача параметров через встроенный язык (классический метод)

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

Рассмотрим этот метод по шагам:

  1. Выполняем первый «вспомогательный» запрос для получения значений фильтрации.
  2. Выгружаем результат запроса в переменные или таблицу значений.
  3. Устанавливаем полученные значения в качестве параметров основного запроса.

Пример кода реализации:


// Шаг 1: Получаем данные для параметров
ЗапросПараметры = Новый Запрос;
ЗапросПараметры.Текст = 
"ВЫБРАТЬ ПЕРВЫЕ 1
|   ТаблицаИсточних.Период КАК ДатаОстатков,
|   ТаблицаИсточних.Организация КАК Организация
|ИЗ
|   РегистрСведений.НастройкиОтчета КАК ТаблицаИсточних";

Результат = ЗапросПараметры.Выполнить();
Выборка = Результат.Выбрать();
Выборка.Следующий();

// Шаг 2: Передаем параметры в основной запрос
ЗапросОсновной = Новый Запрос;
ЗапросОсновной.Текст = 
"ВЫБРАТЬ
|   ХозрасчетныйОстатки.Счет,
|   ХозрасчетныйОстатки.СуммаОстаток
|ИЗ
|   РегистрБухгалтерии.Хозрасчетный.Остатки(&ДатаОстатков, , , Организация = &Организация) КАК ХозрасчетныйОстатки";

ЗапросОсновной.УстановитьПараметр("ДатаОстатков", Выборка.ДатаОстатков);
ЗапросОсновной.УстановитьПараметр("Организация", Выборка.Организация);

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

Решение 2: Использование физических таблиц вместо виртуальных

Если задача стоит сложнее — например, нужно получить остатки на разные даты для разных строк таблицы — метод с параметрами & не поможет, так как параметр в запросе един для всего выполнения. В этом случае выясним причину: виртуальная таблица Остатки — это удобная «обертка», но мы можем обратиться к физическим таблицам итогов или движений напрямую.

Проанализируем ситуацию: мы можем соединить нашу временную таблицу с физической таблицей движений Хозрасчетный.ДвиженияССубконто. Выглядеть это будет так:

  1. Создаем временную таблицу с необходимыми аналитиками и моментами времени.
  2. Соединяем её с таблицей движений по условию Движения.Период <= ВТ.Дата.
  3. Группируем результат, вычисляя остаток как СУММА(СуммаДебет - СуммаКредит).

Важно: Этот метод ресурсозатратен. Для оптимизации работы следует обязательно ограничивать выборку по счетам и организациям во вложенных запросах или условиях соединения ПО.

Решение 3: Соединение с виртуальной таблицей во временной таблице

Если параметров (например, организаций или подразделений) много, но дата одна, мы можем использовать соединение временной таблицы с виртуальной. Выясним, как сделать это правильно, чтобы не «положить» сервер 1С.

Посмотрим на пример правильной структуры пакета запроса:


// Пакет 1: Помещаем нужные нам фильтры во временную таблицу
ВЫБРАТЬ
    ВыбранныеОрганизации.Ссылка КАК Организация
ПОМЕСТИТЬ ВТ_Фильтр
ИЗ
    Справочник.Организации КАК ВыбранныеОрганизации
ГДЕ
    ВыбранныеОрганизации.ПометкаУдаления = ЛОЖЬ;

////////////////////////////////////////////////////////////////////////////////
// Пакет 2: Соединяем ВТ с виртуальной таблицей
ВЫБРАТЬ
    ХозрасчетныйОстатки.Счет,
    ХозрасчетныйОстатки.СуммаОстаток,
    ВТ_Фильтр.Организация
ИЗ
    ВТ_Фильтр КАК ВТ_Фильтр
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Хозрасчетный.Остатки(&Период, , , ) КАК ХозрасчетныйОстатки
        ПО ВТ_Фильтр.Организация = ХозрасчетныйОстатки.Организация

Внимание: При таком подходе крайне важно помнить об особенностях работы оптимизатора. Если в параметрах самой виртуальной таблицы (в скобках) не указан жесткий фильтр по организации, система может сначала попытаться рассчитать остатки по всем организациям базы данных, а уже потом отсечь лишние через ВНУТРЕННЕЕ СОЕДИНЕНИЕ. Поэтому, если есть возможность передать список организаций в параметр через &СписокОрганизаций, это всегда будет быстрее.

Выводы и рекомендации

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

Мы рекомендуем придерживаться следующих правил:

Помните, что чистота кода и производительность запроса часто зависят от того, насколько эффективно вы используете фильтры именно внутри параметров виртуальных таблиц, так как это позволяет серверу СУБД обработать гораздо меньший объем данных еще до этапа соединений таблиц.

← На главную