К статье
Практический материал

Разработка и Конфигурация · 9 мин

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

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

Периодический регистр сведений хранит историю изменения значений во времени: цены, курсы валют, ставки, ФИО, адреса. В прикладных задачах почти всегда нужна не вся история, а актуальное значение на текущий момент или на конкретную дату. Для этого платформа 1С предоставляет виртуальную таблицу «СрезПоследних» и программные методы получения последней записи.

Выбор способа зависит от контекста: в запросе к базе данных удобнее виртуальная таблица, при работе с одним объектом — метод менеджера регистра, а в отчётах на СКД — штатные настройки виртуальной таблицы. Ниже разобраны все основные варианты с примерами кода и типичными ошибками.

Что такое периодичность и срез последних

Регистр сведений становится периодическим, если в его свойствах установлена периодичность: в пределах секунды, дня, месяца, квартала, года или по позиции документа-регистратора. Каждая запись привязана к дате (полю «Период»), и по одному набору измерений может существовать множество значений на разные моменты времени.

Срез последних — это выборка, в которой для каждой комбинации измерений берётся одна запись с максимальным периодом, не превышающим заданную дату. Если дату не указать, срез строится на текущий момент. Аналогично существует «СрезПервых» — первая запись после указанной даты, она нужна реже, например, для поиска даты начала действия значения.

Срез последних в запросе через виртуальную таблицу

Основной способ — обращение к виртуальной таблице СрезПоследних в тексте запроса. В параметрах таблицы передаётся дата среза и, при необходимости, условие отбора по измерениям. Это самый быстрый вариант, когда нужны актуальные значения сразу по многим объектам.

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Цены.Номенклатура КАК Номенклатура,

| Цены.Цена КАК Цена

|ИЗ

| РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ) КАК Цены";

Запрос.УстановитьПараметр("Период", ТекущаяДатаСеанса());

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

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

"РегистрСведений.КурсыВалют.СрезПоследних(&Период, Валюта = &Валюта)"
bsl
Запрос.Текст = "ВЫБРАТЬ * ИЗ РегистрСведений.КурсыВалют.СрезПоследних(&Период, Валюта В (&СписокВалют)) КАК Курсы";

Получение последнего значения методом ПолучитьПоследнее

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

Отбор = Новый Структура("Валюта", ВалютаСсылка);

ДанныеКурса = РегистрыСведений.КурсыВалют.ПолучитьПоследнее(ТекущаяДатаСеанса(), Отбор);

Если ДанныеКурса.Количество() > 0 Тогда

Курс = ДанныеКурса.Курс;

КонецЕсли;

Первый параметр — дата среза, второй — структура отбора по измерениям. Если записей нет, метод возвращает структуру с незаполненными значениями ресурсов, поэтому перед использованием результата стоит проверять его заполненность, иначе в расчётах появятся нулевые курсы или пустые цены.

Срез последних в отчётах на СКД

В системе компоновки данных виртуальная таблица подключается так же — через текст запроса набора данных. Дату среза удобно передавать параметром, который пользователь задаёт в настройках отчёта, либо вычислять автоматически через выражение &Период с привязкой к стандартному периоду.

Частая задача — отчёт, показывающий актуальные цены или статусы на выбранную дату. Здесь достаточно одного набора данных со срезом последних и соединения со справочником для вывода дополнительных реквизитов. Соединение делайте левым, чтобы объекты без записей в регистре тоже попадали в отчёт с пустым значением — так видно, по каким позициям данные вообще не заданы.

Порядок действий
  1. 1
    Определите, нужна выборка по одному объекту или по многим
  2. 2
    Для многих объектов напишите запрос к виртуальной таблице СрезПоследних с датой в параметре
  3. 3
    Для одного объекта используйте РегистрыСведений.ИмяРегистра.ПолучитьПоследнее(Дата, Отбор)
  4. 4
    Проверьте результат на объектах без записей в регистре
  5. 5
    Убедитесь, что отбор задан в параметрах виртуальной таблицы, а не в секции ГДЕ

Работа с регистром, подчинённым регистратору

Если периодичность регистра установлена «По позиции регистратора», записи принадлежат документам, и срез строится с учётом момента времени документа. Виртуальная таблица СрезПоследних работает и в этом случае, но важно понимать: последней считается запись документа с наибольшим моментом времени, а не просто с наибольшей датой.

При ручном изменении таких регистров через запрос нужна осторожность: перепроведение документов может перезаписать данные. Если требуется срез «на конец дня», передавайте в параметр дату со временем 23:59:59 либо объект «Граница» с видом «Включая», иначе записи, сделанные в течение дня, могут не попасть в выборку.

Производительность и оптимизация

Срез последних — ресурсоёмкая операция: платформа группирует записи по измерениям и ищет максимальный период. На регистрах с миллионами записей запрос без отбора может выполняться заметное время. Основные приёмы ускорения: задавать условие по измерениям в параметрах виртуальной таблицы, ограничивать список выбираемых полей и не делать срез по всему регистру, если нужна лишь часть данных.

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

Типичные ошибки
01
Условие по измерениям в секции ГДЕ вместо параметров виртуальной таблицы — срез строится по всему регистру, запрос тормозит
02
Передача даты без времени — записи за текущий день теряются
03
Вызов ПолучитьПоследнее в цикле — сотни обращений к базе вместо одного запроса
04
Отсутствие проверки пустого результата — в расчёты попадают нулевые значения
05
Путаница между СрезПоследних и СрезПервых — выбирается не та запись

Проверка корректности результата

После написания запроса проверьте его на контрольных данных: заведите в копии базы тестовый объект с несколькими записями на разные даты и убедитесь, что срез возвращает именно последнюю из них. Дополнительно проверьте объект без единой записи — он не должен попадать в выборку при внутреннем соединении и должен давать пустое значение при левом соединении.

Для отладки удобно просматривать физические записи регистра через список в режиме предприятия или консоль запросов: сравните максимальный период по измерению с тем, что вернул срез. Совпадение подтверждает корректность даты среза и отбора.

Контрольные точки

Как проверить результат

Дата среза
Норма

В выборку попадает запись с максимальным периодом, не превышающим дату

Тревожный признак

Попадает более ранняя запись или запись из будущего

Объект без записей
Норма

Отсутствует в выборке или имеет пустое значение при левом соединении

Тревожный признак

Возвращает устаревшее значение соседнего объекта

Записи за текущий день
Норма

Учитываются при срезе на сегодня

Тревожный признак

Игнорируются из-за даты без времени

Частые вопросы

Можно ли получить срез последних без запроса, целиком в коде?

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

Что вернёт срез, если по измерению нет ни одной записи?

Виртуальная таблица просто не содержит строки по этому измерению — комбинация не появится в результате. Метод ПолучитьПоследнее вернёт структуру с пустыми значениями ресурсов, поэтому результат нужно проверять перед использованием.

Как получить последние значения на каждую дату периода, а не на одну дату?

Одним срезом это не решается. Обычно строят соединение таблицы дат с регистром по условию «период меньше или равен дате» с группировкой по максимуму периода, либо используют несколько срезов. В отчётах СКД для таких задач применяют характеристики и вычисляемые поля.

Чем СрезПоследних отличается от СрезПервых?

СрезПоследних возвращает ближайшую запись до указанной даты включительно, СрезПервых — ближайшую запись после даты. Второй вариант нужен, например, чтобы узнать, когда значение изменится в будущем или когда оно впервые появилось.

Работает ли срез последних для непериодического регистра?

Нет. Виртуальные таблицы СрезПоследних и СрезПервых существуют только у периодических регистров сведений. У непериодического регистра по каждому набору измерений хранится единственная запись, поэтому срез не нужен — данные читаются напрямую.

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

Передавайте дату документа (или его момент времени для регистратора) в параметр виртуальной таблицы. Тогда срез покажет значения, актуальные на момент документа, что важно для корректного расчёта цен и курсов в проведении.

Итог

Что важно запомнить

Последние значения периодического регистра сведений получают через виртуальную таблицу СрезПоследних в запросе или методом ПолучитьПоследнее для одного объекта. Отбор задавайте в параметрах виртуальной таблицы, дату передавайте с учётом времени, а результат всегда проверяйте на объектах без записей.