Почему при отборе по значению НЕОПРЕДЕЛЕНО в параметрах виртуальной таблицы СрезПоследних поле всегда пустое?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При работе с языком запросов 1С начинающие (а иногда и опытные) разработчики сталкиваются с парадоксальной ситуацией: при установке фильтра по значению НЕОПРЕДЕЛЕНО в параметрах виртуальной таблицы СрезПоследних, в результат попадают только те записи, где это поле действительно не заполнено. Однако, если тот же самый отбор перенести в секцию ГДЕ, результат получается иным. Давайте разберем по шагам, почему так происходит, как платформа 1С обрабатывает эти условия «под капотом» и как правильно проектировать такие запросы.

Различие в механизме работы параметров виртуальной таблицы и секции ГДЕ

Для начала проанализируем фундаментальное различие в выполнении запроса. Это самый важный момент, определяющий логику работы с виртуальными таблицами. Рассмотрим ситуацию, когда мы обращаемся к регистру сведений ПервоначальныеСведенияОС.

Когда мы указываем условие в параметрах виртуальной таблицы, система выполняет следующие действия:

  1. Обращается к физической таблице регистра.
  2. Сначала отфильтровывает только те записи, которые удовлетворяют условию (в нашем примере: ДокументСнятияСУчета = НЕОПРЕДЕЛЕНО).
  3. Затем среди оставшихся записей ищет самую актуальную (последнюю по времени) для каждого измерения.

В результате, если в истории изменений объекта была запись с заполненным документом, но после нее (или до нее) была запись, где документ равен НЕОПРЕДЕЛЕНО, система проигнорирует «заполненную» запись, так как она не прошла фильтр на первом этапе. Вы получите срез не на текущий момент, а «срез среди пустых значений».

Теперь рассмотрим, что происходит, когда условие указано в секции ГДЕ:

  1. Платформа сначала вычисляет виртуальную таблицу СрезПоследних без учета вашего специфического условия по реквизиту. Она находит актуальное состояние для каждого объекта на указанную дату.
  2. После этого к полученному результату (актуальному срезу) применяется фильтр ГДЕ.
  3. Если в актуальном состоянии поле заполнено, а вы просили НЕОПРЕДЕЛЕНО, такая строка просто пропадет из итоговой выборки.

Разбор практического примера

Проанализируем пример кода, который вызвал затруднение:


ВЫБРАТЬ
    ПервоначальныеСведенияОССрезПоследних.ОсновноеСредство КАК ОсновноеСредство,
    ПервоначальныеСведенияОССрезПоследних.ДокументСнятияСУчета КАК ДокументСнятияСУчета,
    ТИПЗНАЧЕНИЯ(ПервоначальныеСведенияОССрезПоследних.ДокументСнятияСУчета) КАК Поле1
ИЗ
    РегистрСведений.ПервоначальныеСведенияОС.СрезПоследних(
            ,
            ОсновноеСредство = &ОсновноеСредство
                И ДокументСнятияСУчета = НЕОПРЕДЕЛЕНО) КАК ПервоначальныеСведенияОССрезПоследних

В данном случае, если для автомобиля «FORD TOURNEO CUSTOM» в регистре есть запись от 01.01.2023, где ДокументСнятияСУчета заполнен, и запись от 01.12.2022, где он равен НЕОПРЕДЕЛЕНО, запрос вернет запись от 2022 года. Почему? Потому что запись 2023 года была отсечена фильтром в параметрах таблицы еще до начала расчета среза. Вы фактически просите систему: «Найди мне последнюю запись в истории, где документ НЕ был указан».

Если же ваша цель — проверить, что в текущий момент (согласно актуальному срезу) документ не заполнен, запрос должен выглядеть так:


ВЫБРАТЬ
    ПервоначальныеСведенияОССрезПоследних.ОсновноеСредство КАК ОсновноеСредство,
    ПервоначальныеСведенияОССрезПоследних.ДокументСнятияСУчета КАК ДокументСнятияСУчета
ИЗ
    РегистрСведений.ПервоначальныеСведенияОС.СрезПоследних(, ОсновноеСредство = &ОсновноеСредство) КАК ПервоначальныеСведенияОССрезПоследних
ГДЕ
    ПервоначальныеСведенияОССрезПоследних.ДокументСнятияСУчета = НЕОПРЕДЕЛЕНО

Особенности значения НЕОПРЕДЕЛЕНО в 1С

Важно помнить, что НЕОПРЕДЕЛЕНО — это специфическое значение для составных типов данных в 1С. Рассмотрим нюансы, которые помогут избежать ошибок:

Влияние на производительность и индексацию

Выясним причину, по которой иногда программисты стремятся запихнуть все условия в параметры виртуальной таблицы. Считается, что это ускоряет запрос, так как уменьшает объем данных, обрабатываемых при расчете среза. Однако здесь есть «подводные камни»:

  1. Индексы: Фильтрация в параметрах эффективна, если поле является измерением регистра. Измерения всегда входят в индексы таблиц итогов.
  2. Реквизиты: Если поле (как ДокументСнятияСУчета) является реквизитом, то оно не входит в индекс таблицы итогов (среза). В этом случае фильтрация в параметрах виртуальной таблицы может привести к полному сканированию физической таблицы регистра, что значительно медленнее, чем получение среза по измерениям и последующая фильтрация в ГДЕ.

Когда использовать параметры, а когда ГДЕ?

Проанализируем типичные сценарии использования:

1. Используйте параметры виртуальной таблицы, если:

2. Используйте секцию ГДЕ, если:

Резюме

Система 1С ведет себя штатным образом, когда возвращает НЕОПРЕДЕЛЕНО при фильтре в параметрах. Вы сами ограничили область поиска записями, в которых это значение пустое. Если ваша логика предполагает получение актуального документа (или его отсутствия), всегда сначала получайте срез по ключевым измерениям, а проверку на заполненность реквизитов выполняйте в секции ГДЕ. Это гарантирует, что вы анализируете текущую реальность базы данных, а не случайные исторические записи, подошедшие под условие фильтра.

← На главную