Как построить вертикальный иерархический отчет по нескольким измерениям регистра накопления

Программист 1С v8.3 (Обычные формы) Управленческий учет Промышленность, строительство и АПК
← На главную

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

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

Способ 1. Использование оператора ОБЪЕДИНИТЬ ВСЕ (UNION ALL)

Первый и самый надежный способ — это нормализация данных внутри самого запроса. Если нам нужно вывести значения разных измерений в одну колонку, мы должны «развернуть» таблицу. Мы создадим запрос, который выбирает каждое измерение по отдельности и объединяет их в общий результат.

Рассмотрим пример построения такого запроса:


ВЫБРАТЬ
    Регистр.Измерение1 КАК ЗначениеИзмерения,
    "Этап 1" КАК НазваниеЭтапа,
    Регистр.СуммаПриход КАК Сумма
ИЗ
    РегистрНакопления.ВашРегистр.Обороты КАК Регистр
ГДЕ
    Регистр.Измерение1 <> ЗНАЧЕНИЕ(Справочник.ВашСправочник.ПустаяСсылка)

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

ВЫБРАТЬ
    Регистр.Измерение2,
    "Этап 2",
    Регистр.СуммаПриход
ИЗ
    РегистрНакопления.ВашРегистр.Обороты КАК Регистр
ГДЕ
    Регистр.Измерение2 <> ЗНАЧЕНИЕ(Справочник.ВашСправочник.ПустаяСсылка)

Этот подход позволяет нам собрать все значимые данные в одну колонку ЗначениеИзмерения. После этого в системе компоновки данных (СКД) мы сможем легко сгруппировать результат по этой колонке.

Способ 2. Использование конструкции ИТОГИ ПО

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

Проанализируем пример запроса с использованием итогов:


ВЫБРАТЬ
    Измерение5,
    Измерение4,
    Измерение3,
    Измерение2,
    Измерение1,
    СуммаОстаток
ИЗ
    РегистрНакопления.ВашРегистр.Остатки
ИТОГИ
    СУММА(СуммаОстаток)
ПО
    Измерение5,
    Измерение4,
    Измерение3,
    Измерение2,
    Измерение1

Важный момент: при таком подходе, если в записи заполнены только Измерение 1 и Измерение 2, а остальные пустые, в отчете могут появиться пустые уровни группировок. Чтобы этого избежать, в настройках СКД или при обработке результата запроса необходимо установить флаг «Игнорировать пустые значения» или использовать отбор в самом запросе.

Способ 3. Реализация через систему компоновки данных (СКД)

Если мы работаем в современной версии платформы, наиболее элегантным решением будет использование группировок в СКД. Мы можем не использовать сложные конструкции ИТОГИ ПО в тексте запроса, а настроить иерархию непосредственно в схеме компоновки.

  1. Создадим набор данных — запрос, который выбирает все необходимые измерения и ресурсы.
  2. Перейдем на закладку «Настройки».
  3. Добавим иерархическую структуру группировок: создаем группировку по Измерению 5, внутрь нее помещаем группировку по Измерению 4, далее по Измерению 3 и так далее.
  4. Для того чтобы отчет выглядел «вертикально», в настройках каждой группировки можно указать тип вывода — «Элементы».

Выясним причину, почему этот способ часто оказывается предпочтительнее: СКД автоматически оптимизирует запросы к базе данных и корректно обрабатывает пустые ссылки в измерениях, не создавая лишних пустых строк в отчете, если правильно настроены ресурсы.

Архитектурные риски и оптимизация производительности

Рассмотрим ситуацию с точки зрения производительности системы. Использование регистра накопления, в котором в одной записи заполнено 5 измерений, а в другой — другие 5, является серьезным вызовом для СУБД. Проанализируем последствия:

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

Во-вторых, при большом количестве объединений (UNION) в запросе, MS SQL Server может столкнуться с проблемой распараллеливания, что иногда приводит к блокировкам типа intra-query parallelism deadlocks. Чтобы этого избежать, старайтесь не делать слишком много объединений в одном запросе. Если уровней передела больше 10, лучше использовать временные таблицы для предварительного сбора данных.

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

Заключение

Мы разобрали три основных способа построения вертикального отчета. Выбор конкретного метода зависит от ваших требований к производительности и сложности структуры данных. В большинстве случаев комбинация UNION ALL во временную таблицу и последующая группировка в СКД дает наиболее предсказуемый и управляемый результат.

← На главную