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