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