При работе с языком запросов 1С разработчики часто сталкиваются с ситуацией: в секции ВЫБРАТЬ указаны все необходимые поля шапки и строк, добавлена секция ИТОГИ с группировкой по определенному идентификатору, однако при обходе выборки с типом ОбходРезультатаЗапроса.ПоГруппировкам значения большинства колонок (например, склад, дата документа, контрагент) оказываются пустыми.
Разберем причины такого поведения платформы 1С и рассмотрим проверенные способы получения заполненных данных.
Когда в тексте запроса используется секция ИТОГИ, платформа формирует иерархическую структуру данных. В итоговых строках (на уровне группировки) значения рассчитываются и заполняются исключительно для следующих полей:
ПО для текущего уровня иерархии (в примере автора — ИдентификаторОперации).ИТОГИ заданы агрегатные функции: СУММА, МАКСИМУМ, МИНИМУМ, КОЛИЧЕСТВО или СРЕДНЕЕ.Все остальные колонки, выбранные в секции ВЫБРАТЬ, на уровне группировочной записи не вычисляются и содержат значение NULL (при обходе выборки во встроенном языке они отображаются как пустые значения соответствующих типов).
Если нам необходимо сохранить иерархическую структуру — получить итоговые суммы по операциям, а затем обработать строки документа или конкретные реквизиты — организуем двухуровневый обход результата запроса.
Посмотрим на пример кода обработки результата:
РезультатЗапроса = Запрос.Выполнить();
// Выбираем верхний уровень группировки
ВыборкаОперации = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам, "ИдентификаторОперации");
Пока ВыборкаОперации.Следующий() Цикл
// На этом уровне доступны: ИдентификаторОперации, итоги по Сумма и Количество
// Получаем подчиненные детальные записи для текущей операции
ВыборкаДетальныеЗаписи = ВыборкаОперации.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
// Здесь доступны все детальные поля: Склад, НомерДок, ДатаОперации, Номенклатура и т.д.
ТекСклад = ВыборкаДетальныеЗаписи.Склад;
ТекНоменклатура = ВыборкаДетальныеЗаписи.Наименование;
КонецЦикла;
КонецЦикла;
При таком подходе реквизиты строк и шапки считываются на уровне детальных записей внутри каждой отдельной группировки.
Если определенные реквизиты (например, склад, организация, контрагент) однозначно соответствуют одной операции и должны быть доступны сразу на верхнем уровне группировки ВыборкаОперации, применим к ним агрегатные функции МАКСИМУМ или МИНИМУМ в секции итогов.
Проанализируем обновленный текст запроса:
ВЫБРАТЬ
Приход.ИдентификаторОперации КАК ИдентификаторОперации,
Приход.Склад КАК Склад,
Приход.ДатаДок КАК ДатаОперации,
Приход.НомерДок КАК НомерДок,
Приход.Поставщик КАК НаименованиеПоставщика,
Приход.ИННПоставщика КАК ИННПоставщика,
Приход.КПППоставщика КАК КПППоставщика,
Приход.ТоварНаименование КАК Наименование,
Приход.ЕдиницаИзмерения КАК ЕдиницаИзмерения,
Приход.Валюта КАК Валюта,
Приход.Количество КАК Количество,
Приход.Сумма КАК Сумма
ИЗ
ТЗПриходы КАК Приход
ИТОГИ
СУММА(Количество),
СУММА(Сумма),
МАКСИМУМ(Склад),
МАКСИМУМ(ДатаОперации),
МАКСИМУМ(НомерДок),
МАКСИМУМ(НаименованиеПоставщика)
ПО
ИдентификаторОперации
Обратите внимание: использование функций МАКСИМУМ или МИНИМУМ корректно работает только тогда, когда значения этих полей строго одинаковы в рамках одного ИдентификаторОперации. Если в исходных данных по одной операции окажется несколько разных складов, в итог попадет только одно максимальное по алфавиту значение.
Если задача заключается в получении плоской свернутой таблицы без детальных строк, секцию ИТОГИ использовать не нужно. Вместо этого применим классическую группировку СГРУППИРОВАТЬ ПО.
Рассмотрим структуру такого запроса:
ВЫБРАТЬ
Приход.ИдентификаторОперации КАК ИдентификаторОперации,
Приход.Склад КАК Склад,
Приход.ДатаДок КАК ДатаОперации,
Приход.НомерДок КАК НомерДок,
Приход.Поставщик КАК НаименованиеПоставщика,
СУММА(Приход.Количество) КАК Количество,
СУММА(Приход.Сумма) КАК Сумма
ИЗ
ТЗПриходы КАК Приход
СГРУППИРОВАТЬ ПО
Приход.ИдентификаторОперации,
Приход.Склад,
Приход.ДатаДок,
Приход.НомерДок,
Приход.Поставщик
Обход такого результата выполняется в один цикл с параметром ОбходРезультатаЗапроса.Прямой, при этом все поля будут гарантированно заполнены в каждой строке выборки.
При передаче параметра ТаблицаЗначений в запрос для помещения во временную таблицу важно следить за тем, чтобы все колонки таблицы имели строго определенное ОписаниеТипов. Если тип данных колонки не задан или определен как Неопределено, вычисление агрегатных функций (например, МАКСИМУМ) и группировок может приводить к ошибкам СУБД или некорректным результатам выборки.