При разработке отчетов на Системе компоновки данных (СКД) разработчики часто сталкиваются с ситуацией, когда сложный запрос, состоящий из нескольких частей с объединениями (ОБЪЕДИНИТЬ ВСЕ), прекрасно работает в обычной консоли запросов, но выдает пустой результат или некорректные цифры при запуске через компоновку данных. Особенно остро эта проблема проявляется, когда в запросах используются последовательные периоды — например, когда дата конца одной части запроса является датой начала для другой части.
В этой статье мы подробно разберем, почему СКД искажает поведение параметров в таких запросах, рассмотрим внутренние механизмы работы компоновщика и предоставим пошаговые инструкции по решению этой проблемы.
Главным виновником такого поведения является механизм Автозаполнения (флаг Автозаполнение на вкладке Наборы данных в СКД). По умолчанию этот флаг всегда включен для новых наборов данных типа "Запрос".
Проанализируем, что происходит за кулисами, когда СКД обрабатывает наш запрос:
СрезПоследних, Обороты или ОстаткиИОбороты), она пытается оптимизировать работу с базой данных. Если автозаполнение включено, СКД принудительно заменяет ваши собственные параметры периодов (такие как &ПериодС или &ПериодПо) на стандартные глобальные параметры схемы.{} — это расширение языка запросов СКД, которое делает параметры необязательными. Если СКД считает, что параметр не заполнен или не настроен должным образом на вкладке параметров, она просто исключает его из запроса к виртуальной таблице, что приводит к неконтролируемому срезу данных.Рассмотрим подробнее три основных способа решения этой проблемы, начиная от самого простого и заканчивая наиболее гибким и удобным для конечного пользователя.
Если вам не требуется, чтобы СКД автоматически добавляла доступные поля и управляла отборами в виртуальных таблицах, самым простым решением будет отключение механизма автозаполнения. В этом случае СКД выполнит ваш запрос ровно в том виде, в каком вы написали его в конструкторе, не пытаясь подменять параметры.
Разберем этот процесс по шагам:
Этот способ гарантирует, что ваши последовательные параметры (например, &ПериодС как конец первой части и начало второй) отработают корректно, как в обычной консоли запросов.
Если вам все же необходимо сохранить преимущества автозаполнения (например, для динамического наложения отборов в виртуальных таблицах), мы можем использовать явное объявление параметров с помощью фигурных скобок. Однако здесь важно правильно настроить их поведение на вкладке параметров.
Рассмотрим пример запроса, в котором первая часть получает срез последних на определенную дату, а вторая часть выбирает обороты за последующий период:
ВЫБРАТЬ
ЦеныНоменклатурыСрезПоследних.Номенклатура КАК Номенклатура,
ЦеныНоменклатурыСрезПоследних.Цена КАК Цена
ИЗ
РегистрСведений.ЦеныНоменклатуры.СрезПоследних({&ПериодС}, ) КАК ЦеныНоменклатурыСрезПоследних
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
ПродажиОбороты.Номенклатура,
ПродажиОбороты.СуммаОборот
ИЗ
РегистрНакопления.Продажи.Обороты({&ПериодС}, {&ПериодПо}, , ) КАК ПродажиОбороты
Чтобы этот запрос не терял данные при выполнении, выполним следующую настройку:
ПериодС и ПериодПо.Заставлять конечного пользователя вводить несколько промежуточных дат (например, дату начала отчета, промежуточную стыковочную дату и дату окончания) — плохая практика проектирования интерфейсов. Мы можем настроить систему так, чтобы пользователь выбирал один стандартный период, а все остальные технические параметры рассчитывались автоматически с помощью встроенного языка выражений СКД.
Проанализируем, как настроить автоматический расчет стыковочных периодов:
ПериодОтчета с типом данных СтандартныйПериод.&ПериодС и &ПериодПо установим флаг Ограничение доступности. Это скроет их из формы настроек отчета, чтобы не запутывать пользователя.&ПериодС (который является концом первой части и началом второй) пропишем формулу расчета. Например, если нам нужно получить дату начала периода отчета:
&ПериодОтчета.ДатаНачала.&ПериодПо в этой же колонке укажем выражение конца периода:
&ПериодОтчета.ДатаОкончания.Если по логике вашего отчета промежуточная дата должна рассчитываться как определенное смещение (например, ровно один месяц от начала периода), мы можем использовать встроенные функции СКД. Например:
ДобавитьКДате(&ПериодОтчета.ДатаНачала, "Месяц", 1)
При работе со стыками дат в СКД очень часто возникает классическая проблема "последней секунды". Виртуальная таблица СрезПоследних рассчитывает остатки или значения на **начало** указанной секунды. Если документ проведен ровно в граничную секунду (например, 31.12.2025 23:59:59), то простой срез на эту дату может не захватить изменения.
Чтобы гарантировать точное попадание всех данных на стыках периодов, рекомендуется в выражениях параметров СКД смещать конечную границу времени на одну секунду вперед. Для этого в колонке Выражение для конечных дат используйте следующую конструкцию:
ДобавитьКДате(КонецПериода(&ПериодПо, "День"), "Секунда", 1)
Это выражение автоматически приводит дату к концу дня (время 23:59:59) и добавляет одну секунду, перенося границу на 00:00:00 следующего дня. Такой подход позволяет виртуальной таблице гарантированно получить актуальный срез данных, включая документы, проведенные последней секундой дня.
Применяя описанные методики работы с параметрами компоновки данных и отключая автозаполнение в сложных неоднородных запросах, мы можем гибко управлять получением данных и строить сложные аналитические отсчеты без потери информации на стыках временных периодов.