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