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