Почему СКД вырезает поля из временных таблиц в запросе и как это исправить?

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

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

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

Причины автоматической оптимизации запроса в СКД

Проанализируем, как работает система компоновки данных при формировании итогового макета. В отличие от обычной консоли запросов, СКД выполняет глубокую оптимизацию пакета запросов перед его отправкой на СУБД:

  1. Исключение неиспользуемых полей: Если поле из промежуточной временной таблицы напрямую не выводится в финальный результат отчета, не задействовано в текущих пользовательских группировках или отборах, компоновщик макета считает его лишним и вырезает из секции ПОМЕСТИТЬ.
  2. Ограничение анализа цепочек временных таблиц: В сложных пакетах из нескольких последовательных временных таблиц компоновщик не всегда корректно отслеживает косвенное участие поля в последующих вычислениях. В результате поле удаляется из первичной таблицы, несмотря на то, что оно необходимо дальше по цепочке.
  3. Обработка фигурных скобок {}: Конструкции вида {(&НачалоПериода)} предназначены для необязательных параметров СКД. Если параметр внутри параметров виртуальной таблицы обособлен фигурными скобками, но не указан в пользовательских настройках, СКД полностью убирает его из итогового запроса.

Рассмотрим пример исходного запроса, помещающего данные во временную таблицу:


ВЫБРАТЬ
    СебестоимостьОстаткиИОбороты.Регистратор КАК Регистратор,
    СебестоимостьОстаткиИОбороты.Номенклатура КАК Номенклатура,
    СебестоимостьОстаткиИОбороты.КоличествоПриход КАК КоличествоПриход,
    СебестоимостьОстаткиИОбороты.СуммаПриход КАК СуммаПриход,
    СебестоимостьОстаткиИОбороты.КоличествоРасход КАК КоличествоРасход,
    СебестоимостьОстаткиИОбороты.СуммаРасход КАК СуммаРасход
ПОМЕСТИТЬ ВТ_Регистр
ИЗ
    РегистрНакопления.Себестоимость.ОстаткиИОбороты({(&НачалоПериода)}, {(&КонецПериода)}, Регистратор, , ) КАК СебестоимостьОстаткиИОбороты

При вызове в СКД без дополнительных настроек компоновщик генерирует модифицированный текст, исключая из временной таблицы ВТ_Регистр расходные показатели и параметры периода:


ВЫБРАТЬ
    СебестоимостьОстаткиИОбороты.Регистратор КАК Регистратор,
    СебестоимостьОстаткиИОбороты.Номенклатура КАК Номенклатура,
    СебестоимостьОстаткиИОбороты.КоличествоПриход КАК КоличествоПриход,
    СебестоимостьОстаткиИОбороты.СуммаПриход КАК СуммаПриход
ПОМЕСТИТЬ ВТ_Регистр
ИЗ
    РегистрНакопления.Себестоимость.ОстаткиИОбороты(, , Регистратор, , ) КАК СебестоимостьОстаткиИОбороты

Способ 1. Установка флага «Обязательное» в настройках компоновки

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

Разберем по шагам, как это сделать:

  1. Откроем схему компоновки данных и перейдем на вкладку Наборы данных.
  2. В нижней части экрана перейдем на вкладку Компоновка данных.
  3. Найдем в списке нужные поля (например, КоличествоРасход и СуммаРасход).
  4. В колонке Обязательное установим флаг для каждого из этих полей.

После этого компоновщик перестанет исключать указанные поля из состава секции ВЫБРАТЬ временной таблицы.

Способ 2. Использование вложенного запроса

Если оптимизатор СКД продолжает вырезать поля из-за цепочки связей, можно применить вложенный запрос внутри выборки. Это изолирует логику получения данных и предотвращает удаление полей компоновщиком.

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


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

Способ 3. Отказ от фигурных скобок в параметрах виртуальных таблиц

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


РегистрНакопления.Себестоимость.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Регистратор, , )

В этом случае СКД всегда будет передавать значения параметров &НачалоПериода и &КонецПериода в виртуальную таблицу, не исключая их из текста итогового запроса.

Способ 4. Использование функций ЕСТЬNULL или фиктивных условий

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

Обертывание поля в функцию ЕСТЬNULL дает сигнал компоновщику, что поле участвует в вычислениях:

ЕСТЬNULL(СебестоимостьОстаткиИОбороты.СуммаРасход, 0) КАК СуммаРасход

Также можно добавить фиктивное условие в последующих запросах пакета, где используется временная таблица ВТ_Регистр:


ГДЕ
    ВТ_Регистр.СуммаРасход = ВТ_Регистр.СуммаРасход

Такое условие показывает оптимизатору СКД, что поле СуммаРасход задействовано в логике пакета, благодаря чему оно сохраняется в первичной временной таблице.

← На главную