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