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

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

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

В данной статье мы подробно разберем, как правильно «подтянуть» дату последнего движения к остаткам, рассмотрим различные способы реализации этой задачи и проанализируем нюансы производительности каждого метода.

Метод 1. Использование временной таблицы и поиск максимального периода

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

Рассмотрим пошагово, как составить такой запрос. Представим, что у нас есть регистр накопления Расш_Бюджет с измерениями Организация и Проект.

Шаг 1. Получение последних дат движений

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


ВЫБРАТЬ
    Расш_Бюджет.Организация КАК Организация,
    Расш_Бюджет.Проект КАК Проект,
    МАКСИМУМ(Расш_Бюджет.Период) КАК ПериодПоследнегоДвижения
ПОМЕСТИТЬ ВТ_ПоследниеДаты
ИЗ
    РегистрНакопления.Расш_Бюджет КАК Расш_Бюджет
ГДЕ
    Расш_Бюджет.Период <= &ДатаКонца
    И Расш_Бюджет.Активность = ИСТИНА
СГРУППИРОВАТЬ ПО
    Расш_Бюджет.Организация,
    Расш_Бюджет.Проект;

Проанализируем этот фрагмент кода. Обратите внимание на условие Активность = ИСТИНА. Это критически важный момент: если документ был отменен или запись сторнирована, она все равно остается в физической таблице, но перестает влиять на остатки. Без этого фильтра вы рискуете получить дату документа, который фактически не участвует в формировании остатка.

Шаг 2. Соединение остатков с полученными датами

Теперь мы можем получить остатки из виртуальной таблицы и приклеить к ним нашу дату из временной таблицы ВТ_ПоследниеДаты.


ВЫБРАТЬ
    Остатки.Организация КАК Организация,
    Остатки.Проект КАК Проект,
    Остатки.БюджетОстаток КАК БюджетОстаток,
    ЕСТЬNULL(ПоследниеДаты.ПериодПоследнегоДвижения, ДАТАВРЕМЯ(1, 1, 1)) КАК ДатаПоследнегоДвижения
ИЗ
    РегистрНакопления.Расш_Бюджет.Остатки(&ДатаКонца, ) КАК Остатки
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ПоследниеДаты КАК ПоследниеДаты
    ПО Остатки.Организация = ПоследниеДаты.Организация
    И Остатки.Проект = ПоследниеДаты.Проект

Выясним причину использования ЛЕВОЕ СОЕДИНЕНИЕ. Мы используем его для того, чтобы в отчет попали все остатки, даже если по какой-то причине (например, после свертки базы) записи в физической таблице отсутствуют, а итоги в виртуальной таблице есть. Функция ЕСТЬNULL поможет корректно обработать пустые значения дат.

Метод 2. Использование виртуальной таблицы «Остатки и Обороты»

Существует альтернативный способ — использование виртуальной таблицы ОстаткиИОбороты с периодичностью Регистратор. Рассмотрим подробнее этот подход. Система позволяет вызывать таблицу следующим образом:


ВЫБРАТЬ
    Бюджет.Организация,
    Бюджет.Проект,
    Бюджет.Период КАК ДатаДвижения,
    Бюджет.Регистратор,
    Бюджет.БюджетКонечныйОстаток
ИЗ
    РегистрНакопления.Расш_Бюджет.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Регистратор, , ) КАК Бюджет

Однако разберем по шагам, почему этот метод может быть опасен:

  1. Производительность: Таблица ОстаткиИОбороты с детализацией до регистратора заставляет систему рассчитывать остаток на момент каждого движения. Если у вас тысячи документов за период, запрос будет выполняться крайне медленно.
  2. Избыточность: Вы получите список всех движений с остатком после каждого из них, а не только последнее. Вам придется накладывать дополнительные фильтры (например, ВЫБРАТЬ ПЕРВЫЕ 1 с сортировкой по периоду убывания), что еще сильнее усложнит запрос.

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

Проблема точности: Период против Момента времени

Рассмотрим ситуацию, когда в одну и ту же секунду (один и тот же Период) было проведено два документа. Если мы ищем просто МАКСИМУМ(Период), мы найдем время, но не сможем однозначно определить, какой документ был «последним» в логической последовательности 1С.

Если вам нужно получить не просто дату, а именно ссылку на Регистратор, рекомендуется использовать следующий алгоритм:

  1. Найдите максимальный Период для каждого измерения (как в Методе 1).
  2. Поместите результат во временную таблицу.
  3. Соедините эту таблицу снова с физической таблицей регистра по измерениям и периоду, чтобы получить МАКСИМУМ(МоментВремени).
  4. И только после этого соединяйте с остатками.

Это гарантирует, что даже при совпадении секунд вы выберете тот документ, который стоит последним в последовательности базы данных.

Анализ производительности и индексы

Посмотрим на ситуацию со стороны СУБД. Когда мы делаем СГРУППИРОВАТЬ ПО измерениям физической таблицы, 1С обращается к индексам. Чтобы запрос из Метода 1 летал «молниеносно», убедитесь, что в конфигураторе у измерений Организация и Проект включено свойство «Индексировать» (или «Индексировать с доп. упорядочиванием»).

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

Практические советы при работе с остатками и датами

Проанализируем еще несколько важных моментов, которые помогут избежать ошибок:

Подводя итог, можно сказать, что наиболее надежным и профессиональным способом является использование Метода 1 с предварительным сбором максимальных дат во временную таблицу. Это обеспечивает чистоту кода, высокую скорость работы и легкость отладки запроса в консоли.

← На главную