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