Довольно часто разработчики сталкиваются с проблемой получения актуального состояния (статуса) объекта на определенный момент времени. Разберем типичную ситуацию: статусы записываются документами-регистраторами, но в качестве хранилища ошибочно выбран оборотный регистр накопления. При попытке вывести в отчет объекты по определенному "последнему" статусу возникают серьезные сложности, так как стандартные выборки не помогают, а в результат попадают объекты, статус которых уже изменился. Проанализируем причину этой проблемы и рассмотрим правильные архитектурные решения.
Регистры накопления (как оборотные, так и остаточные) в архитектуре 1С предназначены исключительно для работы с количественными и суммовыми показателями — ресурсами, которые можно складывать или вычитать. Статус же является качественным показателем, то есть просто состояниям.
Если мы укажем статус как измерение оборотного регистра, платформа сможет агрегировать обороты в разрезе этого статуса за период, но штатно определить хронологическую последовательность смены состояний она не сможет. Главная проблема заключается в том, что у регистров накопления просто нет встроенных виртуальных таблиц для получения первого или последнего значения (среза).
Выясним, как правильно реализовать задачу на уровне метаданных. Для хранения истории изменения состояний объектов необходимо использовать периодический регистр сведений (например, подчиненный регистратору или с периодичностью в пределах секунды).
Именно периодичность дает доступ к главной платформенной виртуальной таблице для подобных задач — СрезПоследних. При построении отчета ваш запрос должен обращаться именно к ней.
Рассмотрим важное правило оптимизации: чтобы отчет работал быстро, фильтр по нужному статусу следует передавать в параметры самой виртуальной таблицы (в параметр условия), а не использовать отбор в секции ГДЕ. Это кардинально снизит нагрузку на базу данных при выполнении запроса, так как СУБД отфильтрует данные до формирования итоговой выборки.
Если данные уже были накоплены в старом регистре, правильным решением будет создать новый регистр сведений и однократно заполнить его историческими данными из регистра накопления.
Разберем ситуацию, когда по каким-то причинам отказаться от оборотного регистра нельзя (например, существует строгий запрет на изменение архитектуры старой базы). Получить последние статусы можно с помощью сложного запроса к физической таблице движений регистра. Выполним следующие шаги:
МАКСИМУМ(Период). Для исключения коллизий, когда в одну секунду записано несколько статусов, надежнее получать МАКСИМУМ(МоментВремени) или использовать автосгенерированный внутренний идентификатор записи, если он доступен в контексте запроса.Важно: этот метод имеет серьезный недостаток — крайне низкую производительность на больших объемах данных. Платформе приходится сканировать, группировать и соединять всю физическую таблицу движений, что делает отчет медленным.
Посмотрим на задачу под другим углом. Если бизнес-логика не требует получения статуса "на дату в прошлом" (то есть историчность изменений не важна), а нужен только актуальный текущий статус на данную секунду, оптимальнее всего добавить реквизит ТекущийСтатус непосредственно в сам справочник (в нашем примере — справочник сим-карт).
В этом случае при проведении документов-регистраторов мы просто перезаписываем значение этого реквизита в элементе справочника. Это обеспечит самую высокую скорость работы любых отчетов, так как полностью исключит необходимость обращения к таблицам регистров и расчет срезов последних записей.