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