При перенесении готового пакета запросов из консоли запросов в Систему компоновки данных (СКД) разработчики часто сталкиваются со следующей ситуацией: запрос, который успешно выполнялся в консоли, в СКД теряет часть полей во временных таблицах или перестает учитывать параметры виртуальных таблиц.
Разберем подробно причины такого поведения компоновщика макета и рассмотрим проверенные способы сохранения нужных полей во временных таблицах.
Проанализируем, как работает система компоновки данных при формировании итогового макета. В отличие от обычной консоли запросов, СКД выполняет глубокую оптимизацию пакета запросов перед его отправкой на СУБД:
ПОМЕСТИТЬ.{}: Конструкции вида {(&НачалоПериода)} предназначены для необязательных параметров СКД. Если параметр внутри параметров виртуальной таблицы обособлен фигурными скобками, но не указан в пользовательских настройках, СКД полностью убирает его из итогового запроса.Рассмотрим пример исходного запроса, помещающего данные во временную таблицу:
ВЫБРАТЬ
СебестоимостьОстаткиИОбороты.Регистратор КАК Регистратор,
СебестоимостьОстаткиИОбороты.Номенклатура КАК Номенклатура,
СебестоимостьОстаткиИОбороты.КоличествоПриход КАК КоличествоПриход,
СебестоимостьОстаткиИОбороты.СуммаПриход КАК СуммаПриход,
СебестоимостьОстаткиИОбороты.КоличествоРасход КАК КоличествоРасход,
СебестоимостьОстаткиИОбороты.СуммаРасход КАК СуммаРасход
ПОМЕСТИТЬ ВТ_Регистр
ИЗ
РегистрНакопления.Себестоимость.ОстаткиИОбороты({(&НачалоПериода)}, {(&КонецПериода)}, Регистратор, , ) КАК СебестоимостьОстаткиИОбороты
При вызове в СКД без дополнительных настроек компоновщик генерирует модифицированный текст, исключая из временной таблицы ВТ_Регистр расходные показатели и параметры периода:
ВЫБРАТЬ
СебестоимостьОстаткиИОбороты.Регистратор КАК Регистратор,
СебестоимостьОстаткиИОбороты.Номенклатура КАК Номенклатура,
СебестоимостьОстаткиИОбороты.КоличествоПриход КАК КоличествоПриход,
СебестоимостьОстаткиИОбороты.СуммаПриход КАК СуммаПриход
ПОМЕСТИТЬ ВТ_Регистр
ИЗ
РегистрНакопления.Себестоимость.ОстаткиИОбороты(, , Регистратор, , ) КАК СебестоимостьОстаткиИОбороты
Самый штатный инструмент управления полем в СКД — явное указание его обязательности. Если необходимо, чтобы поле гарантированно попадало во временную таблицу независимо от выбранных полей отчета, его нужно пометить как обязательное.
Разберем по шагам, как это сделать:
КоличествоРасход и СуммаРасход).После этого компоновщик перестанет исключать указанные поля из состава секции ВЫБРАТЬ временной таблицы.
Если оптимизатор СКД продолжает вырезать поля из-за цепочки связей, можно применить вложенный запрос внутри выборки. Это изолирует логику получения данных и предотвращает удаление полей компоновщиком.
Посмотрим на пример переписанного запроса с использованием вложенной выборки:
ВЫБРАТЬ
ВложенныйЗапрос.Регистратор КАК Регистратор,
ВложенныйЗапрос.Номенклатура КАК Номенклатура,
ВложенныйЗапрос.КоличествоРасход КАК КоличествоРасход,
ВложенныйЗапрос.СуммаРасход КАК СуммаРасход
ПОМЕСТИТЬ ВТ_Регистр
ИЗ
(ВЫБРАТЬ
СебестоимостьОстаткиИОбороты.Регистратор КАК Регистратор,
СебестоимостьОстаткиИОбороты.Номенклатура КАК Номенклатура,
СебестоимостьОстаткиИОбороты.КоличествоРасход КАК КоличествоРасход,
СебестоимостьОстаткиИОбороты.СуммаРасход КАК СуммаРасход
ИЗ
РегистрНакопления.Себестоимость.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Регистратор, , ) КАК СебестоимостьОстаткиИОбороты) КАК ВложенныйЗапрос
Выясним, почему урезаются параметры дат. Использование фигурных скобок {(&НачалоПериода)} указывает СКД на то, что параметр является опциональным. Если требуется жестко зафиксировать период для временной таблицы, необходимо передавать параметры напрямую без фигурных скобок:
РегистрНакопления.Себестоимость.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Регистратор, , )
В этом случае СКД всегда будет передавать значения параметров &НачалоПериода и &КонецПериода в виртуальную таблицу, не исключая их из текста итогового запроса.
Еще один практический прием — принудительное применение выражений к полям во временной таблице или создание фиктивных связей в последующих запросах пакета.
Обертывание поля в функцию ЕСТЬNULL дает сигнал компоновщику, что поле участвует в вычислениях:
ЕСТЬNULL(СебестоимостьОстаткиИОбороты.СуммаРасход, 0) КАК СуммаРасход
Также можно добавить фиктивное условие в последующих запросах пакета, где используется временная таблица ВТ_Регистр:
ГДЕ
ВТ_Регистр.СуммаРасход = ВТ_Регистр.СуммаРасход
Такое условие показывает оптимизатору СКД, что поле СуммаРасход задействовано в логике пакета, благодаря чему оно сохраняется в первичной временной таблице.