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