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

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

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

Почему метод ПолучитьПоследнее не возвращает дату?

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

Это связано с идеологией метода: он предназначен для получения текущего состояния объекта на определенный момент времени, а не для анализа истории. С точки зрения платформы, вам важно «какое сейчас значение», а не «когда оно было установлено». Если же вам критически важна дата возникновения этого состояния, необходимо использовать другие инструменты.

Важно помнить, что под капотом метода ПолучитьПоследнее() скрывается обычный SQL-запрос. Платформа генерирует конструкцию SELECT TOP 1 с сортировкой по периоду в обратном порядке. Таким образом, использование этого метода не дает выигрыша в производительности по сравнению с запросом, а лишь сокращает объем написанного кода, при этом ограничивая состав получаемых данных.

Вариант 1: Использование метода менеджера СрезПоследних

Если мы хотим остаться в рамках объектной техники (без написания текста запроса), но при этом нам нужна дата записи, мы можем воспользоваться методом СрезПоследних(). В отличие от ПолучитьПоследнее(), этот метод возвращает не структуру, а таблицу значений (ТаблицаЗначений).

Проанализируем пример получения последнего пробега автомобиля с датой его фиксации:


// Подготовим отбор по измерениям
СтруктураОтбора = Новый Структура;
СтруктураОтбора.Вставить("Автомобиль", СсылкаНаАвтомобиль);
СтруктураОтбора.Вставить("ВидЗначения", Перечисления.ДополнительнаяИнформацияАвтомобилей.Пробег);

// Получаем таблицу значений (срез последних)
ТаблицаРезультата = РегистрыСведений.Автомобили.СрезПоследних(ТекущаяДата(), СтруктураОтбора);

// Проверяем, есть ли записи в результате
Если ТаблицаРезультата.Количество() > 0 Тогда
    ПоследняяЗапись = ТаблицаРезультата[0];
    ДатаЗаписи = ПоследняяЗапись.Период;
    ЗначениеПробега = ПоследняяЗапись.Значение;
    
    Сообщить("Последний пробег: " + ЗначениеПробега + " зафиксирован " + ДатаЗаписи);
КонецЕсли;

Преимущества этого метода:

  1. В таблице значений всегда присутствует колонка Период.
  2. Код пишется в несколько строк без использования конструктора запросов.

Важное предостережение: Метод СрезПоследних() (как и ПолучитьПоследнее()) крайне не рекомендуется использовать внутри циклов. Каждое обращение — это отдельный запрос к базе данных. Если вам нужно получить даты для списка из 100 автомобилей, вы получите 100 обращений к СУБД, что значительно замедлит работу системы. В таких случаях нужно использовать только полноценный запрос.

Вариант 2: Использование языка запросов (рекомендуемый способ)

Как справедливо заметили участники обсуждения, использование запроса — это наиболее профессиональный и гибкий подход. Запрос позволяет получить только нужные поля, управлять нагрузкой на сервер и эффективно обрабатывать данные массивами.

Рассмотрим, как правильно составить запрос к виртуальной таблице СрезПоследних для получения даты записи:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	АвтомобилиСрезПоследних.Период КАК ДатаЗаписи,
    |	АвтомобилиСрезПоследних.Значение КАК Пробег
    |ИЗ
    |	РегистрСведений.Автомобили.СрезПоследних(&ПериодГраница, Автомобиль = &Автомобиль И ВидЗначения = &ВидИнформации) КАК АвтомобилиСрезПоследних";

Запрос.УстановитьПараметр("Автомобиль", Ведро); // Ссылка на объект
Запрос.УстановитьПараметр("ВидИнформации", Перечисления.ДополнительнаяИнформацияАвтомобилей.Пробег);
Запрос.УстановитьПараметр("ПериодГраница", ТекущаяДата());

РезультатЗапроса = Запрос.Выполнить();

Если НЕ РезультатЗапроса.Пустой() Тогда
    Выборка = РезультатЗапроса.Выбрать();
    Выборка.Следующий();
    
    Возврат Выборка.ДатаЗаписи;
КонецЕсли;

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

Сравнение методов и работа на уровне SQL

Выясним причину, почему опытные разработчики настаивают на запросах. Когда вы вызываете ПолучитьПоследнее(), платформа транслирует это в SQL примерно так:

SELECT TOP 1 ResourceValue FROM InformationRegisterTable WHERE Dimension1 = @P1 ORDER BY Period DESC

Когда вы используете СрезПоследних в запросе, механизм может быть сложнее. Если для регистра включено использование итогов среза последних, система мгновенно возьмет данные из специальной таблицы итогов. Если итоги не включены или период не актуален (на дату в прошлом), система построит подзапрос для поиска максимального периода по каждому набору измерений.

Основные выводы нашего анализа:

  1. Объектный метод ПолучитьПоследнее: Не возвращает дату. Подходит только для быстрого получения значения «здесь и сейчас» в коде, где дата не важна.
  2. Метод менеджера СрезПоследних: Возвращает дату в колонке Период. Удобен для получения данных в одну-две строки, но опасен при использовании в циклах.
  3. Запрос к виртуальной таблице СрезПоследних: Самый универсальный и производительный метод. Позволяет получать данные по спискам объектов и гибко настраивать состав полей.

Рекомендации по индексации

Чтобы поиск последней даты был мгновенным, проанализируйте структуру вашего регистра. В периодических регистрах сведений индекс автоматически строится по полям Период + Измерения. Однако для эффективной работы среза последних часто требуется индекс в обратном порядке: Измерения + Период. В свойствах регистра сведений убедитесь, что у ведущих измерений (в нашем случае Автомобиль) стоит признак Основной отбор. Это позволит платформе эффективно находить последнюю запись по конкретному транспортному средству.

Таким образом, если перед вами стоит задача получить дату последней записи, лучшим выбором будет использование Запроса к виртуальной таблице. Это гарантирует масштабируемость вашего кода и его стабильную работу при росте объема данных в регистре.

← На главную