В каких случаях нужно использовать условия в параметрах виртуальной таблицы «СрезПоследних»?

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

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

Проблема: Почему «СрезПоследних» возвращает старые данные?

Рассмотрим классическую ситуацию, с которой столкнулся автор темы. В информационной базе есть регистр сведений, хранящий историю должностей сотрудников. Сотрудник Халиков в 2015 году был «Менеджером», а в 2018 году стал «Директором». Если мы хотим узнать, является ли он сейчас менеджером, мы ожидаем получить пустой результат. Но если мы передадим условие Должность = &Менеджер непосредственно в параметры виртуальной таблицы, запрос вернет нам запись от 2015 года.

Проанализируем ситуацию: почему так происходит? Все дело во внутренней логике работы платформы и формируемом SQL-запросе. Когда условие помещается в параметры виртуальной таблицы, система ищет самую позднюю запись, которая удовлетворяет этому условию. То есть запрос буквально звучит так: «Найди мне момент времени, когда Халиков в последний раз был Менеджером». И система его находит, игнорируя тот факт, что позже была запись «Директор».

Разберем по шагам: Механика фильтрации

Для глубокого понимания процесса разделим два способа наложения условий в запросе:

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

    Платформа формирует вложенный запрос к физической таблице регистра. В этом вложенном запросе сразу применяется фильтр. Если мы указали должность, система отсекает все записи с другими должностями еще до того, как начнет определять максимальную дату (период). В итоге «последней» становится запись, которая была актуальна много лет назад.

  2. Условие в предложении ГДЕ (после выборки из ВТ):

    В этом случае виртуальная таблица сначала отрабатывает «честно»: она находит действительно самую последнюю запись для данного сотрудника в регистре (запись «Директор»). Затем, когда результат уже получен, к нему применяется фильтр ГДЕ. Так как «Директор» не равен «Менеджеру», эта строка исключается из итогового результата. Мы получаем пустой набор данных, что и является логически верным ответом на вопрос «Является ли Халиков сейчас менеджером?».

Когда использовать параметры виртуальной таблицы?

Несмотря на описанную выше проблему, фильтрация внутри виртуальной таблицы — это стандарт де-факто для обеспечения высокой производительности. Выясним причины, по которым условия нужно вставлять в параметры ВТ:

Когда использовать предложение ГДЕ?

Условие следует выносить в секцию ГДЕ в следующих случаях:

Измерения против Ресурсов

Важно помнить о структуре самого регистра. Посмотрим на разницу:

Если Должность в вашем регистре является Измерением, то система хранит историю в разрезе каждой должности. В этом случае сотрудник может одновременно занимать две должности. Тогда СрезПоследних с фильтром по должности вернет актуальное состояние именно по этой позиции.

Если Должность является Ресурсом (что чаще встречается в кадровом учете), то у сотрудника в один момент времени может быть только одна должность. Здесь и кроется ошибка автора: для ресурса нельзя использовать фильтр внутри ВТ, если цель — узнать текущий статус.

Пример правильного и неправильного кода

Рассмотрим ситуацию на языке запросов. Допустим, нам нужно найти всех сотрудников, которые на данный момент являются «Менеджерами».

Неправильный подход (вернет тех, кто когда-либо был менеджером и это была их последняя запись в этой роли):


ВЫБРАТЬ
    ИсторияДолжностейСрезПоследних.Сотрудник,
    ИсторияДолжностейСрезПоследних.Должность
ИЗ
    РегистрСведений.ИсторияДолжностей.СрезПоследних(&Период, Должность = &ДолжностьМенеджер) КАК ИсторияДолжностейСрезПоследних

Правильный подход (вернет только тех, у кого текущая актуальная должность — менеджер):


ВЫБРАТЬ
    ИсторияДолжностейСрезПоследних.Сотрудник,
    ИсторияДолжностейСрезПоследних.Должность
ИЗ
    РегистрСведений.ИсторияДолжностей.СрезПоследних(&Период, ) КАК ИсторияДолжностейСрезПоследних
ГДЕ
    ИсторияДолжностейСрезПоследних.Должность = &ДолжностьМенеджер

Резюме и рекомендации

Проанализировав механику работы платформы, мы можем сформулировать золотое правило:

Условия в параметрах виртуальной таблицы используйте для отсечения ненужных разрезов (измерений), а условия в секции ГДЕ — для фильтрации полученного актуального состояния.

Также стоит учитывать нюансы конкретных конфигураций. Как отмечали участники обсуждения, в некоторых кадровых системах при смене организации или повторном приеме на работу создается новый элемент справочника Сотрудники. В этом случае срез по конкретному сотруднику Халикову (старому) всегда будет показывать «Менеджер», так как для него это действительно была последняя запись в истории. Будьте внимательны к данным, на которых строится ваш запрос!

← На главную