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

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

При работе с регистрами накопления в 1С начинающие разработчики часто сталкиваются с вопросом: как правильно сгруппировать данные при получении остатков? В классическом SQL для этого требуется явно указывать все неагрегированные поля в конструкции GROUP BY. Однако механизм виртуальных таблиц 1С работает иначе, упрощая жизнь разработчику, но требуя понимания внутренних процессов платформы.

Механизм работы виртуальной таблицы остатков

Рассмотрим ситуацию, когда у нас есть регистр накопления с измерениями Заказчик, Груз, МестоПогрузки и ресурсом Вес. Если нам необходимо получить остатки только в разрезе груза и места погрузки (проигнорировав заказчика), нам не нужно писать сложные группировки.

В языке запросов 1С виртуальная таблица Остатки (например, РегистрНакопления.МойРегистр.Остатки) автоматически суммирует ресурсы по тем измерениям, которые выбраны в блоке ВЫБРАТЬ. Если вы исключаете измерение Заказчик из списка полей запроса, система сама "схлопнет" (просуммирует) все значения веса по уникальным комбинациям груза и места погрузки.

Проанализируем пример кода, который решает задачу автора:


ВЫБРАТЬ
    ОстаткиГруза.Груз КАК Груз,
    ОстаткиГруза.МестоПогрузки КАК МестоПогрузки,
    ОстаткиГруза.ВесОстаток КАК Вес
ИЗ
    РегистрНакопления.МойРН.Остатки(&Период, ) КАК ОстаткиГруза

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

Использование параметров виртуальной таблицы

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

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


ВЫБРАТЬ
    ОстаткиГруза.Груз,
    ОстаткиГруза.МестоПогрузки,
    ОстаткиГруза.ВесОстаток
ИЗ
    РегистрНакопления.МойРН.Остатки(&Период, МестоПогрузки = &ВыбранноеМесто) КАК ОстаткиГруза

Важный момент: использование фильтра внутри скобок Остатки(...) позволяет СУБД отсечь ненужные записи на самом раннем этапе, что значительно ускоряет выполнение запроса по сравнению с использованием предложения ГДЕ в конце запроса.

Точность данных и объект Граница

Выясним причину, по которой иногда остатки могут казаться неверными. При получении остатков на "момент времени" документа важно понимать, включены ли движения этого документа в расчет. Для этого в 1С используется объект Граница.

  1. Если нужно получить остатки до проведения текущего документа, используется ВидГраницы.Исключая.
  2. Если нужно получить остатки с учетом движений текущего документа, используется ВидГраницы.Включая.

Передавая объект Граница в первый параметр виртуальной таблицы (&Период), мы гарантируем точность итогов в любой точке временной шкалы.

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

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

Если вы часто запрашиваете остатки без измерения Заказчик, но это измерение стоит первым в списке измерений регистра, СУБД может выполнять сканирование индекса вместо быстрого поиска. Если отчеты без Заказчика являются критически важными и частыми, стоит рассмотреть изменение порядка измерений или создание дополнительных индексов (хотя в типовых решениях это чаще решается оптимизацией самих запросов).

Обработка пустых значений (NULL)

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

Рассмотрим, как правильно обрабатывать такие случаи в коде запроса:


ВЫБРАТЬ
    СправочникГрузы.Ссылка КАК Груз,
    ЕСТЬNULL(Остатки.ВесОстаток, 0) КАК Вес
ИЗ
    Справочник.Грузы КАК СправочникГрузы
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.МойРН.Остатки(&Период, ) КАК Остатки
    ПО СправочникГрузы.Ссылка = Остатки.Груз

Функция ЕСТЬNULL заменяет пустое значение нулем, что позволяет корректно выводить данные в отчеты и использовать их в дальнейших арифметических вычислениях.

Использование временных таблиц для сложных расчетов

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


ВЫБРАТЬ
    Остатки.Груз,
    Остатки.ВесОстаток
ПОМЕСТИТЬ ВТ_Остатки
ИЗ
    РегистрНакопления.МойРН.Остатки(&Период, ) КАК Остатки
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ_Остатки.Груз,
    ВТ_Остатки.ВесОстаток
ИЗ
    ВТ_Остатки КАК ВТ_Остатки

Такой подход делает код более читаемым и зачастую помогает оптимизатору запросов СУБД построить более эффективный план выполнения.

← На главную