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