Почему при использовании итогов в запросе 1С пропадают строки и как правильно вывести детальные записи?

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

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

Разбор проблемы: ИТОГИ против СГРУППИРОВАТЬ

Давайте проанализируем ситуацию, описанную в теме. Автор столкнулся с тем, что до применения итогов в таблице были все нужные суммы (несколько записей с одинаковыми аналитическими данными, но разными или одинаковыми суммами). После добавления ИТОГИ МАКСИМУМ(Сумма) ПО Ссылка в выборке осталась только одна запись с максимальным значением. Чтобы понять причину, нам нужно четко разграничить два инструмента языка запросов:

  1. СГРУППИРОВАТЬ ПО: этот оператор работает на уровне СУБД и физически «схлопывает» записи. Если вы группируете данные, детальные записи теряются безвозвратно, превращаясь в одну итоговую строку.
  2. ИТОГИ ПО: этот оператор не удаляет детальные записи. Вместо этого он строит иерархическую структуру (дерево). В результате запроса появляются дополнительные строки — итоговые записи по группам, но сами исходные данные (детальные записи) остаются в выборке, просто они находятся на «нижнем» уровне иерархии.

Выясним причину: Проблема автора сообщения (0) заключалась не в самом запросе, а в способе обработки его результата. Если мы обращаемся к результату запроса линейно, мы видим только верхний уровень — те самые итоги.

Программный обход иерархической выборки

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

Давайте разберем по шагам правильный алгоритм обхода:


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

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

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

Пока ВыборкаГруппировка.Следующий() Цикл
    // Здесь мы видим ИТОГОВОЕ значение (Максимум) по конкретной Ссылке
    Сообщить("Документ: " + ВыборкаГруппировка.Ссылка + " Макс. сумма: " + ВыборкаГруппировка.Сумма);
    
    // 3. Чтобы увидеть детальные записи (те самые 4 записи по 177к), 
    // нужно "провалиться" внутрь этой группировки
    ВыборкаДетальные = ВыборкаГруппировка.Выбрать();
    
    Пока ВыборкаДетальные.Следующий() Цикл
        // Здесь доступны все детальные записи, входящие в итог
        Сообщить("   Детальная строка, сумма: " + ВыборкаДетальные.Сумма);
    КонецЦикла;
КонецЦикла;

Проанализируем ситуацию: когда автор в сообщении (6) говорит, что он «провалился на еще один уровень», он имеет в виду именно этот вложенный цикл. Если использовать обычный Результат.Выбрать() без параметров, 1С вернет «плоскую» таблицу, но поведение итогов в ней может сбивать с толку, так как итоги будут перемешаны с детальными записями.

Особенности агрегатных функций в итогах

Важно понимать, как работают функции СУММА, МАКСИМУМ, КОЛИЧЕСТВО в секции итогов. Рассмотрим подробнее:

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

Влияние порядка полей в ИТОГИ ПО

Порядок следования полей в инструкции ИТОГИ ПО... строго определяет вложенность уровней в объекте ВыборкаИзРезультатаЗапроса. Посмотрим на пример:


ИТОГИ
    СУММА(Сумма)
ПО
    Организация,
    Склад,
    Номенклатура

В этом случае структура обхода должна быть трехступенчатой: сначала мы выбираем организации, внутри каждой организации выбираем склады, а внутри каждого склада — номенклатуру. Только на самом последнем уровне (после вызова Выбрать() из выборки по номенклатуре) мы получим детальные записи. Если пропустить один из уровней, логика данных может быть нарушена.

Работа с NULL и пустыми значениями

При расчете итогов часто возникают ситуации, когда итоговые поля содержат NULL. Это случается, например, при использовании ЛЕВОЕ СОЕДИНЕНИЕ. Проанализируем, как это влияет на результат:

Если в данных есть NULL, механизм итогов создаст для них отдельную группировку. Чтобы отчет выглядел корректно и программа не «падала» при попытке обращения к свойствам пустых ссылок, всегда рекомендуется использовать функцию ЕСТЬNULL() в основной части запроса:


ВЫБРАТЬ
    ЕСТЬNULL(Продажи.СуммаОборот, 0) КАК Сумма
...
ИТОГИ
    СУММА(Сумма)
ПО
    ...

Производительность и рекомендации

Хотя использование итогов в запросе кажется удобным, следует помнить о производительности. Когда СУБД (например, MS SQL или PostgreSQL) выполняет запрос с итогами, она фактически выполняет несколько операций агрегации и сортировки. В некоторых случаях, если вам нужно просто вывести список в отчет, использование итогов в самом запросе оправдано. Однако, если данных очень много (миллионы строк), иногда эффективнее получить плоскую таблицу и сгруппировать ее уже средствами встроенного языка или использовать Систему компоновки данных (СКД).

Подведем итог нашего исследования:

  1. Данные при использовании ИТОГИ не пропадают — они становятся подчиненными итоговым записям.
  2. Для доступа к детальным записям необходимо использовать иерархический обход через Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам).
  3. Функция МАКСИМУМ (или любая другая) в итогах влияет только на значения в строках-группировках, не изменяя детальные данные.
  4. Тщательно следите за уровнями вложенности и порядком полей в секции ПО.

Следуя этим правилам, вы сможете эффективно строить сложные иерархические отчеты и корректно обрабатывать любые объемы информации в системе 1С.

← На главную