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