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