Как вывести уровень иерархии в рекурсивном запросе СКД при выводе в плоскую таблицу?

Программист 1С:ERP Управление предприятием Управленческий учет Промышленность, строительство и АПК
← На главную

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

Метод 1. Использование параметров связи наборов данных

Проанализируем самый эффективный способ получения уровня иерархии непосредственно в механизмах СКД без изменения структуры запроса. Этот метод основан на передаче текущего значения уровня в следующий шаг рекурсии через параметры связи.

Разберем алгоритм по шагам:

  1. В наборе данных, который выступает «приемником» в связи (тот же набор данных при самосоединении), создадим параметр, например, П_Уровень.
  2. В настройках связи наборов данных на закладке «Связи наборов данных» укажем связь нашего набора с самим собой.
  3. В колонке «Параметры» для этой связи добавим наш параметр П_Уровень.
  4. В качестве выражения для параметра укажем: Уровень + 1.

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

Метод 2. Борьба с зацикливанием данных с помощью поля «Путь»

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

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


// Пример логики формирования пути в запросе
ВЫБРАТЬ
    Номенклатура,
    Количество,
    &ПутьРодителя + "/" + ПРЕДСТАВЛЕНИЕ(Номенклатура) КАК Путь
ИЗ
    Справочник.Спецификации.Состав
ГДЕ
    НЕ &ПутьРодителя ПОДОБНО "%" + ПРЕДСТАВЛЕНИЕ(Номенклатура) + "%"

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

Метод 3. Матричный метод расчета (СЛАУ)

Рассмотрим более продвинутый математический подход, который упоминался как решение через СЛАУ (Систему линейных алгебраических уравнений). Этот метод особенно актуален для пищевой промышленности (например, мясопереработки), где количество связей и аналогов огромно.

Суть метода заключается в представлении состава изделия в виде матрицы прямых затрат. Если у нас есть 100 видов номенклатуры, мы создаем матрицу 100х100, где в ячейках указано количество вхождения одного элемента в другой. Решение такой системы позволяет получить полные затраты материалов на единицу продукции за один проход, полностью избегая рекурсивных запросов ВЫБРАТЬ внутри циклов. В 1С это реализуется через временные таблицы и итерационный пересчет коэффициентов вхождения в пакетном запросе.

Метод 4. Архитектурное решение через дополнительный регистр

Если отчет должен работать очень быстро у оператора на производстве, выполнение сложных рекурсивных расчетов «на лету» может быть неприемлемым. Рассмотрим вариант с предварительным расчетом состава.

Создадим специализированный регистр сведений «Состав изделия по модификациям». При записи или утверждении спецификации будем программно разузловывать её и записывать в регистр уже готовую «плоскую» структуру со следующими реквизитами:

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

Метод 5. Использование шаблонов спецификаций для аналогов

Проанализируем ситуацию с аналогами. Когда у каждого компонента есть 3-5 аналогов, количество веток дерева растет в геометрической прогрессии. Чтобы упростить задачу, можно использовать метод спецификаций-шаблонов:

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

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

Важный момент: если вы решите использовать вычисляемые поля СКД для расчета уровня, помните, что обращение к функциям общих модулей из СКД замедляет выполнение отчета, так как функция будет вызываться для каждой строки результата. Использование параметров связи (Метод 1) является наиболее «нативным» и быстрым способом для платформы 1С:Предприятие 8.3.

← На главную