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