Как получить итоги по группам в запросе 1С 7.7 для измерения с типом «Справочник»?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

При разработке отчетов в платформе 1С:Предприятие 7.7 разработчики нередко сталкиваются с ситуацией, когда после изменения типа измерения регистра с конкретного справочника (например, Справочник.Контрагенты) на универсальный составной тип Справочник (неопределенного вида) встроенный объект Запрос перестает выводить иерархические итоги по группам. Запрос начинает возвращать данные так, как будто в секции группировки жестко указана опция Без Групп.

Проанализируем причины такого поведения платформы и разберем практические способы решения этой задачи.

Причина ограничения встроенного языка запросов 1С 7.7

Выясним причину, по которой платформа отключает иерархию:

  1. Разные физические таблицы: Для реквизита или измерения с типом «Справочник неопределенного вида» в базе данных хранится составное значение, включающее идентификатор вида метаданных и внутренний идентификатор объекта (ID). Встроенный транслятор запросов 1С 7.7 не умеет на лету связывать несколько разных физических таблиц справочников и разворачивать их внутренние связи по полю иерархии PARENTEXT.
  2. Ограничение генератора запросов: Механизм автоматического построения дерева групп в объекте Запрос рассчитан строго на типизированные объекты с однозначно известной структурой метаданных (например, Справочник.Номенклатура или Справочник.Контрагенты). Для составных типов группировка всегда принудительно функционирует в режиме без иерархии.

Таким образом, получить встроенные итоги по группам стандартным текстом запроса при типе Справочник невозможно. Рассмотрим доступные пути обхода этого ограничения.

Способ 1. Программный расчет иерархии через объект «ТаблицаЗначений»

Наиболее распространенный и универсальный способ в штатной конфигурации — выгрузить плоский результат запроса в таблицу значений и программно рассчитать итоговые суммы по родительским группам, поднимаясь по цепочке родителей.

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

  1. Выполняем запрос к регистрам и получаем плоский результат без групп.
  2. Выгружаем данные запроса в объект ТаблицаЗначений с помощью метода Выгрузить().
  3. Создаем результирующую таблицу значений или дерево, куда переносим строки.
  4. Для каждого элемента в цикле получаем его родителя через обращение к атрибуту Родитель и накапливаем суммы на каждом уровне иерархии вплоть до корневого элемента.
  5. Выводим подготовленные данные в отчет с отступами или секциями нужного уровня.

Посмотрим на пример кода обработки иерархии:


// Выполняем запрос
Запрос = СоздатьОбъект("Запрос");
Если Запрос.Выполнить(ТекстЗапроса) = 1 Тогда
    ТабДанных = СоздатьОбъект("ТаблицаЗначений");
    Запрос.Выгрузить(ТабДанных);
    
    // Создаем таблицу для итогов по группам
    ТабИтогов = СоздатьОбъект("ТаблицаЗначений");
    ТабИтогов.НоваяКолонка("Объект");
    ТабИтогов.НоваяКолонка("Уровень", "Число");
    ТабИтогов.НоваяКолонка("Сумма", "Число", 15, 2);
    
    // Обходим детальные записи и рассчитываем родителей
    ТабДанных.ВыбратьСтроки();
    Пока ТабДанных.ПолучитьСтроку() = 1 Цикл
        ТекОбъект = ТабДанных.кли;
        ТекСумма = ТабДанных.сппСумма;
        
        // Поднимаемся вверх по иерархии
        Родитель = ТекОбъект.Родитель;
        Пока Родитель.Выбран() = 1 Цикл
            // Накапливаем итоги по каждой найденной группе
            ТабИтогов.НоваяСтрока();
            ТабИтогов.Объект = Родитель;
            ТабИтогов.Уровень = Родитель.Уровень();
            ТабИтогов.Сумма = ТекСумма;
            
            Родитель = Родитель.Родитель;
        КонецЦикла;
    КонецЦикла;
    
    // Сворачиваем итоги по группам
    ТабИтогов.Свернуть("Объект,Уровень", "Сумма");
КонецЕсли;

Способ 2. Оптимизация архитектуры метаданных

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

  1. Разделение на отдельные типизированные измерения: Если измерение может принимать значения из ограниченного списка справочников (например, только Справочник.Контрагенты и Справочник.Склады), эффективнее завести два раздельных типизированных измерения в регистре. В этом случае стандартный механизм запросов 1С 7.7 сохранит возможность строить итоги по группам для каждого справочника.
  2. Использование мастер-справочника: Создается единый универсальный справочник (например, «Субъекты» или «Партнеры»), в котором выстраивается общая иерархия, а ссылки на конкретные прикладные объекты хранятся в реквизитах. Тогда измерение регистра имеет жесткий тип нового справочника, и запрос работает штатно.

Способ 3. Использование прямых SQL-запросов (Direct SQL)

Для конфигураций, работающих под управлением Microsoft SQL Server с подключенными внешними компонентами прямого доступа к БД, задачу можно решить на уровне SQL:

  1. По первым символам составного идентификатора определяется вид справочника.
  2. Таблица регистра соединяется оператором LEFT JOIN с соответствующей таблицей SCxxx справочника.
  3. Построение дерева и подсчет сумм по родителям выполняется средствами SQL через рекурсивные выражения или вспомогательные процедуры.

Этот подход обеспечивает максимальное быстродействие на больших массивах данных, исключая медленный обход объектов через OLE/COM в цикле 1С 7.7.

← На главную