Почему после добавления секции ИТОГИ запрос в 1С возвращает пустой результат?

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

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

Причина проблемы: разница между Таблицей значений и Деревом значений

Главная причина кажущегося «исчезновения» строк кроется в том, как платформа обрабатывает результаты запросов, содержащих секцию ИТОГИ:

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

Способ 1. Правильный программный обход иерархической выборки

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

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


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

Запрос.УстановитьПараметр("СписокСчетов", СписокСчетов);
Запрос.УстановитьПараметр("ВидыСубконто", ВидыСубконто);

РезультатЗапроса = Запрос.Выполнить();

// 1. Выбираем группировку верхнего уровня (Общий итог)
ВыборкаОбщийИтог = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

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

Способ 2. Выгрузка и прямой обход результата без иерархии

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

Рассмотрим примеры:


// Выгрузка в плоскую Таблицу Значений:
ТаблицаРезультата = РезультатЗапроса.Выгрузить(ОбходРезультатаЗапроса.Прямой);

// Либо последовательный обход всех детальных строк без создания двухуровневой структуры:
ВыборкаПрямая = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.Прямой);
Пока ВыборкаПрямая.Следующий() Цикл
    // Чтение записей подряд
КонецЦикла;

Способ 3. Оптимизация запроса к регистру бухгалтерии

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

  1. Перенос условий в параметры виртуальной таблицы: Условие ХозрасчетныйОстатки.Счет В ИЕРАРХИИ (&СписокСчетов) нельзя указывать в секции ГДЕ. Секция ГДЕ фильтрует строки уже после того, как СУБД рассчитала остатки по всей базе данных. Ограничение по счетам следует передавать во второй параметр виртуальной таблицы: РегистрБухгалтерии.Хозрасчетный.Остатки(&Период, Счет В ИЕРАРХИИ (&СписокСчетов), ...).
  2. Использование временных таблиц: При сложных агрегациях с условиями ИМЕЮЩИЕ разделение логики на пакетный запрос с временной таблицей делает код понятным и гарантирует корректный расчет итогов.

Посмотрим на оптимизированный вариант с использованием временной таблицы:


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

Способ 4. Использование Системы компоновки данных (СКД)

Если задача состоит в построении пользовательского отчета, секцию ИТОГИ в тексте запроса писать не требуется. Рекомендуется использовать СКД:

  1. В схеме компоновки данных пишется простой запрос без ключевого слова ИТОГИ.
  2. На вкладке Ресурсы поля СуммаОстатокДт и СуммаОстатокКт рассчитываются с выражением Сумма(СуммаОстатокДт) и Сумма(СуммаОстатокКт).
  3. На вкладке Настройки формируется структура группировок, и платформа автоматически рассчитывает как промежуточные, так и общие итоги отчета.
← На главную