Как реализовать нарастающий итог в СКД с условием и по разным группировкам?

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

При разработке отчетов в системе компоновки данных (СКД) одной из наиболее часто встречающихся задач является расчет нарастающего итога. Традиционно разработчики пытаются решить эту задачу на уровне запроса, однако при больших объемах данных это приводит к серьезным проблемам с производительностью. В этой статье мы подробно разберем, почему методы запроса могут «тормозить», и как правильно использовать мощный функционал функций ВычислитьВыражение для получения быстрого и гибкого результата.

Метод 1. Реализация нарастающего итога на уровне запроса (Self-Join)

Прежде всего, рассмотрим классический подход через язык запросов. Этот метод основан на левом соединении таблицы самой с собой по условию «меньше или равно». Разберем пример кода, который часто используется в таких случаях:


ВЫБРАТЬ
    т1.Док КАК Док,
    т1.Товар КАК Товар,
    т1.Кол КАК Кол,
    СУММА(т2.Кол) КАК КолВоз
ПОМЕСТИТЬ втИтоги
ИЗ
    Таб КАК т1
ЛЕВОЕ СОЕДИНЕНИЕ Таб КАК т2
    ПО т2.Док <= т1.Док И т2.Товар = т1.Товар
СГРУППИРОВАТЬ ПО
    т1.Док,
    т1.Товар,
    т1.Кол

Проанализируем ситуацию: несмотря на то что этот метод кажется логичным, он имеет огромный недостаток. Сложность такого алгоритма возрастает в квадратичной прогрессии. При увеличении количества записей в выборке время выполнения запроса растет катастрофически. Если на 1000 записей запрос отработает за секунду, то на 100 000 записей система может просто «зависнуть» на десятки минут.

Если вы все же вынуждены использовать этот метод, обязательно следуйте этим советам:

  1. Используйте временные таблицы (ПОМЕСТИТЬ).
  2. Добавьте поле АвтономерЗаписи и проиндексируйте его.
  3. Связывайте таблицы по индексированным числовым полям или датам, чтобы оптимизировать поиск в СУБД.

Метод 2. Использование функции СКД «ВычислитьВыражение»

Перейдем к более современному и производительному способу — использованию функций ресурсов СКД. Этот метод работает после получения данных из базы, непосредственно в памяти в процессе компоновки результата. Это линейный проход по данным, который выполняется в разы быстрее, чем тяжелое SQL-соединение.

Для реализации нарастающего итога нам потребуется настроить поле ресурса. Рассмотрим синтаксис функции ВычислитьВыражение:

ВычислитьВыражение(Выражение, Группировка, ОбластьВычисления, Начало, Конец)

Разберем параметры функции подробнее для нашей задачи:

Итоговая формула в ресурсах будет выглядеть так:


ВычислитьВыражение("Сумма(Количество)", , "Общая", "Первая", "Текущая")

Как реализовать нарастающий итог с условием?

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

Мы используем конструкцию Выбор Когда... прямо внутри текста функции ВычислитьВыражение:


ВычислитьВыражение("Сумма(Выбор Когда ТипОперации = &Приход Тогда Количество Иначе 0 Конец)", , "Общая", "Первая", "Текущая")

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

Решение проблемы сквозного итога по разным группировкам

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

Чтобы решить эту задачу, в параметре Группировка функции ВычислитьВыражение необходимо указать имя конкретного поля, например, "Товар". Это заставит СКД смотреть на последовательность данных именно по этому значению, невзирая на то, в какой части отчета оно выводится.

Пример формулы для сквозного итога по полю:


ВычислитьВыражение("Сумма(Количество)", "Товар", "Общая", "Первая", "Текущая")

Важность упорядочивания данных

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

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

Сводная таблица преимуществ СКД перед запросом

Посмотрим на сравнение двух подходов:

  1. Производительность: СКД выигрывает на больших объемах данных за счет линейной сложности $O(n)$, в то время как запрос с соединением имеет сложность $O(n^2)$.
  2. Гибкость: В СКД проще менять условия накопления и группировки без переписывания текста SQL-запроса.
  3. Читаемость: Формулы в ресурсах СКД короче и нагляднее, чем многоуровневые вложенные запросы с группировками.

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

← На главную