Почему двоятся остатки в общих итогах запроса 1С и как это исправить?

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

При построении отчетов по регистрам бухгалтерии или накопления разработчики часто сталкиваются с ситуацией: при добавлении в выборку детальных полей (например, регистратора или корреспондирующего счета) в секции ОБЩИЕ и на верхних уровнях группировки начальные и конечные остатки начинают многократно суммироваться и выдавать неверный результат.

Разберем подробно, почему возникает эта ошибка, почему попытки обойти её конструкциями условий в секции ИТОГИ не работают, и рассмотрим правильные архитектурные способы решения проблемы.

Выясним причину: почему умножаются остатки при соединении

Проанализируем типовой запрос, в котором таблица остатков связывается через ЛЕВОЕ СОЕДИНЕНИЕ с таблицей детальных оборотов:


ВЫБРАТЬ 
    Основной.Фирма,
    Основной.Субконто1,
    ОсновнойОбороты.Регистратор,
    ОсновнойОбороты.КорСчет,
    Основной.СуммаНачальныйОстаток КАК СуммаНачальныйОстаток,
    ОсновнойОбороты.СуммаОборотДт КАК Приход,
    ОсновнойОбороты.СуммаОборотКт КАК Расход,
    Основной.СуммаКонечныйОстаток КАК СуммаКонечныйОстаток
ИЗ
    РегистрБухгалтерии.Основной.ОстаткиИОбороты(&ДатаНач, &ДатаКон, , , Счет В (&СписокСчетов), ...) КАК Основной
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Основной.Обороты(&ДатаНач, &ДатаКон, Регистратор, Счет В (&СписокСчетов), ...) КАК ОсновнойОбороты
    ПО Основной.Фирма = ОсновнойОбороты.Фирма 
    И Основной.Субконто1 = ОсновнойОбороты.Субконто1
ИТОГИ 
    СУММА(СуммаНачальныйОстаток),
    СУММА(Приход),
    СУММА(Расход),
    СУММА(СуммаКонечныйОстаток)
ПО 
    ОБЩИЕ, 
    Основной.Фирма,
    Основной.Субконто1,
    ОсновнойОбороты.КорСчет,
    ОсновнойОбороты.Регистратор

Механизм возникновения ошибки заключается в следующем:

  1. Таблица остатков сгруппирована по полям Фирма и Субконто1 — в ней для каждой пары аналитики присутствует ровно одна строка.
  2. Таблица оборотов развернута до регистраторов и корсчетов — для одной пары аналитики в ней может быть множество строк (связь 1:N).
  3. В результате соединения строка с остатком дублируется столько раз, сколько документов-регистраторов было проведено по данной аналитике за период.
  4. Секция ИТОГИ рассчитывает агрегат СУММА по всем строкам итоговой таблицы. Соответственно, на уровнях Субконто1, Фирма и ОБЩИЕ остаток складывается сам с собой по числу детальных строк.

Почему не работают условия ВЫБОР внутри секции ИТОГИ

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

Способ 1. Использование конструкции ОБЪЕДИНИТЬ ВСЕ (Рекомендуемый для запросов)

Классический и наиболее надежный способ избежать дублирования остатков в прямом запросе — заменить левое соединение на объединение двух независимых наборов данных. Рассмотрим этот шаблон:

  1. Первая ветка запроса выбирает только остатки. Поля регистратора и корсчета заполняются пустыми ссылками или значениями NULL, а суммы оборотов — нулями.
  2. Вторая ветка запроса выбирает детальные обороты. Поля начального и конечного остатка заполняются нулями.
  3. Обе ветки объединяются через ОБЪЕДИНИТЬ ВСЕ, после чего накладываются итоги.

Посмотрим на пример реализации запроса:


ВЫБРАТЬ
    Остатки.Фирма КАК Фирма,
    Остатки.Субконто1 КАК Субконто1,
    НЕОПРЕДЕЛЕНО КАК Регистратор,
    ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.ПустаяСсылка) КАК КорСчет,
    Остатки.СуммаНачальныйОстаток КАК СуммаНачальныйОстаток,
    0 КАК Приход,
    0 КАК Расход,
    Остатки.СуммаКонечныйОстаток КАК СуммаКонечныйОстаток
ИЗ
    РегистрБухгалтерии.Основной.ОстаткиИОбороты(&ДатаНач, &ДатаКон, , , Счет В (&СписокСчетов), ...) КАК Остатки

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    Обороты.Фирма,
    Обороты.Субконто1,
    Обороты.Регистратор,
    Обороты.КорСчет,
    0,
    Обороты.СуммаОборотДт,
    Обороты.СуммаОборотКт,
    0
ИЗ
    РегистрБухгалтерии.Основной.Обороты(&ДатаНач, &ДатаКон, Регистратор, Счет В (&СписокСчетов), , , КорСчет В (&СписокКорСчетов)) КАК Обороты

ИТОГИ
    СУММА(СуммаНачальныйОстаток),
    СУММА(Приход),
    СУММА(Расход),
    СУММА(СуммаКонечныйОстаток)
ПО
    ОБЩИЕ,
    Фирма,
    Субконто1,
    КорСчет,
    Регистратор

При таком подходе каждая сумма остатка попадает в выборку ровно один раз. На детальных строках оборотов остаток равен нулю, а на уровнях группировок Субконто1, Фирма и ОБЩИЕ вычисляется математически корректная сумма.

Способ 2. Построение отчета с использованием СКД

Если отчет разрабатывается в Системе компоновки данных, платформа решает проблему дублирования остатков встроенными механизмами:

  1. Роли полей: На вкладке «Наборы данных» для числовых полей остатков система автоматически или вручную назначает роли: ОстатокНачальный и ОстатокКонечный. Указываются соответствующие поля периода и счета. СКД самостоятельно управляет алгоритмом сбора итогов и не допускает перемножения остатков при развороте по регистраторам.
  2. Раздельные формулы ресурсов: На вкладке «Ресурсы» в колонке «Рассчитывать по...» можно гибко настроить разные выражения для конкретных группировок, например, отключив расчет остатка на детальных записях по полю КорСчет или Регистратор.

Способ 3. Выделение первой строки во временной таблице

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

  1. Создаем временную таблицу оборотов и с помощью нумерации или группировки по минимальному регистратору определяем «первую» строку для каждой группы аналитики.
  2. В итоговом запросе сумму остатка выбираем через условие: если это первая строка группы — выводим остаток, иначе выводим 0.
  3. В результате сумма по всему набору данных не задваивается, а общий итог сходится с суммой по исходной таблице остатков.
← На главную