К статье
Практический материал

Разработка и Конфигурация · 10 мин

Как в запросе 1С объединить строки в одну

Как объединить строки в одну в запросе 1С: группировка с СОЕДИНИТЬ, функция СоединитьСтроки, обход выборки. Примеры кода, ограничения и типичные ошибки.

Задача объединить несколько строк результата запроса в одну строку возникает в 1С регулярно: нужно собрать список товаров документа в одно поле, вывести все телефоны контрагента через запятую, сформировать строку для печатной формы или CSV-выгрузки. Важно сразу понимать: в языке запросов 1С нет прямого аналога функции GROUP_CONCAT из MySQL или STRING_AGG из MS SQL, поэтому задача решается обходными путями.

Основных подхода три: группировка в запросе с последующей склейкой в коде, использование функций встроенного языка (СтрСоединить, СоединитьСтроки) после выполнения запроса и приёмы с пакетными запросами и временными таблицами. Выбор зависит от того, где нужен результат — в поле запроса, в отчёте СКД или в обычном коде.

Ниже разобраны рабочие варианты с примерами кода, ограничения каждого способа и типичные ошибки, из-за которых склейка получается пустой, обрезанной или с неправильным порядком элементов.

Почему в запросе 1С нельзя просто «склеить» строки группы

Язык запросов 1С — декларативный: он описывает, какие данные выбрать и как их сгруппировать, но не умеет выполнять итеративную обработку внутри группы. Агрегатные функции ограничены стандартным набором: СУММА, КОЛИЧЕСТВО, МИНИМУМ, МАКСИМУМ, СРЕДНЕЕ. Функции «собрать все значения поля в строку» среди них нет.

Оператор «+» в запросе складывает только значения внутри одной строки выборки, а не между строками. Поэтому конструкция вида «Ссылка.Товары.Номенклатура + ", "» на уровне группировки не сработает — запрос либо вернёт ошибку, либо выдаст строки по отдельности.

Вывод: полноценная склейка делается в два этапа — запрос готовит сгруппированные или упорядоченные данные, а объединение выполняет код на встроенном языке. Исключение — отдельные приёмы в СКД, о которых ниже.

Способ 1. Группировка в запросе и склейка обходом выборки

Самый универсальный и надёжный вариант. В запросе выбираются детальные строки с сортировкой по ключу группы, затем в коде строки обходятся и значения накапливаются в массив или строку. Когда ключ меняется — накопленное склеивается и сохраняется.

Пример: нужно для каждого документа получить строку со списком номенклатуры через запятую.

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Товары.Ссылка КАК Документ,

| Товары.Номенклатура.Наименование КАК Наименование

|ИЗ

| Документ.РеализацияТоваровУслуг.Товары КАК Товары

|

|УПОРЯДОЧИТЬ ПО

| Документ";

Выборка = Запрос.Выполнить().Выбрать();

Результат = Новый Соответствие;

ТекущийДокумент = Неопределено;

Части = Новый Массив;

Пока Выборка.Следующий() Цикл

Если ТекущийДокумент <> Выборка.Документ Тогда

Если Части.Количество() > 0 Тогда

Результат.Вставить(ТекущийДокумент, СтрСоединить(Части, ", "));

КонецЕсли;

ТекущийДокумент = Выборка.Документ;

Части = Новый Массив;

КонецЕсли;

Части.Добавить(Выборка.Наименование);

КонецЦикла;

Если Части.Количество() > 0 Тогда

Результат.Вставить(ТекущийДокумент, СтрСоединить(Части, ", "));

КонецЕсли;

Обратите внимание на обязательную обработку последней группы после цикла — это самая частая причина «потери» одного документа в результате. Также важна сортировка по ключу: без УПОРЯДОЧИТЬ ПО Документ строки одной группы могут идти вразнобой, и склейка развалится.

Порядок действий при склейке обходом
  1. 1
    Составьте запрос с детальными строками и добавьте сортировку по ключу группы
  2. 2
    Инициализируйте переменные: текущий ключ и массив частей строки
  3. 3
    В цикле сравнивайте ключ с предыдущим; при смене ключа склейте массив через СтрСоединить и сохраните результат
  4. 4
    После цикла обработайте последнюю накопленную группу
  5. 5
    Проверьте результат на документе с одной строкой и на документе без строк

Способ 2. Группировка в запросе, склейка через Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам)

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

Запрос.Текст =

"ВЫБРАТЬ

| Товары.Ссылка КАК Документ,

| Товары.Номенклатура.Наименование КАК Наименование

|ИЗ

| Документ.РеализацияТоваровУслуг.Товары КАК Товары

|ИТОГИ ПО

| Документ";

ВыборкаДокументы = Запрос.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

Пока ВыборкаДокументы.Следующий() Цикл

Части = Новый Массив;

Детали = ВыборкаДокументы.Выбрать();

Пока Детали.Следующий() Цикл

Части.Добавить(Детали.Наименование);

КонецЦикла;

СтрокаТоваров = СтрСоединить(Части, ", ");

КонецЦикла;

Этот вариант удобнее, когда помимо склеенной строки нужны ещё и итоговые числа по группе (сумма, количество) — они доступны на верхнем уровне выборки без дополнительного запроса.

Способ 3. Склейка в СКД и консоли отчётов

В системе компоновки данных объединить строки группы в одну можно через собственные функции в общем модуле. В вычисляемом поле или ресурсе вызывается функция, которая принимает ключ группы и возвращает склеенную строку. Функция должна быть экспортной и размещаться в общем модуле с флагом «Сервер».

// В общем модуле

Функция СклеитьСтроки(МассивЗначений) Экспорт

Возврат СтрСоединить(МассивЗначений, ", ");

КонецФункции

Другой путь в СКД — вычисляемое поле с выражением на языке выражений компоновки, но его возможности ограничены: полноценной агрегатной склейки строк там нет, поэтому на практике чаще формируют отчёт с детальными строками, а объединение делают при программной обработке результата компоновки.

Способ 4. Функции СтрСоединить и СоединитьСтроки — в чём разница

Для самой склейки в коде используются две функции. СтрСоединить — современная функция, принимает массив строк и разделитель, работает быстро и предсказуемо. СоединитьСтроки — устаревший вариант из ранних версий платформы, в современных конфигурациях лучше применять СтрСоединить.

Если массив содержит не строки, а числа или ссылки, сначала преобразуйте их функцией Строка() или сформируйте нужное представление — иначе получите системное представление значения, которое не всегда читаемо.

Для больших объёмов не склеивайте строку операцией «Строка = Строка + Кусок» в цикле: каждая операция создаёт новую строку в памяти, и на тысячах элементов это заметно тормозит. Накапливайте части в массиве и один раз вызывайте СтрСоединить.

Сравнение способов склейки

Обход линейной выборки

Универсально, работает везде; требует сортировки по ключу и аккуратной обработки последней группы

Выборка по группировкам (ИТОГИ ПО)

Чище код, доступны итоги группы; чуть больше памяти на иерархический результат

Функция в СКД

Результат сразу в отчёте; нужен общий серверный модуль и аккуратность с производительностью

Ограничения и подводные камни

Длина результирующей строки не ограничена жёстко, но если склеенное значение будет выводиться в поле табличного документа или СКД, очень длинные строки портят вёрстку. Разумно ограничивать количество элементов или обрезать строку с добавлением многоточия.

Дубли в склейке — частая проблема. Если в табличной части встречается одна и та же номенклатура несколько раз, она попадёт в строку несколько раз. Решение — перед добавлением проверять Части.Найти(Значение) = Неопределено либо собирать уникальные значения через Соответствие.

Порядок элементов в склеенной строке определяется сортировкой запроса. Если нужен порядок по номеру строки табличной части — добавьте НомерСтроки в выборку и в УПОРЯДОЧИТЬ ПО после ключа группы.

Типичные ошибки
01
Нет сортировки по ключу группы — строки одной группы перемешиваются, склейка разваливается на несколько частей
02
Забыта обработка последней группы после цикла — последний документ теряется
03
Склейка через «Строка + Кусок» в цикле — сильное замедление на больших объёмах
04
Дубли значений в итоговой строке из-за отсутствия проверки уникальности
05
Склейка ссылок без Строка() — в строке появляются нечитаемые системные представления
Контрольные точки

Как проверить результат

Документ с одной строкой
Норма

Строка содержит одно значение без разделителей

Тревожный признак

Лишняя запятая в начале или конце

Документ с несколькими строками
Норма

Все значения присутствуют, порядок соответствует табличной части

Тревожный признак

Пропущены значения или нарушен порядок

Последний документ в выборке
Норма

Присутствует в результате

Тревожный признак

Отсутствует — не обработана последняя группа

Документ без табличной части
Норма

Отсутствует в результате или пустая строка по логике задачи

Тревожный признак

Ошибка обращения к пустой выборке

FAQ

Можно ли объединить строки прямо в тексте запроса без кода?

Нет, в языке запросов 1С нет агрегатной функции склейки строк. Максимум, что доступно в запросе, — сложение полей внутри одной строки выборки. Для объединения значений из разных строк группы всегда нужна обработка результата в коде или в СКД.

Чем заменить GROUP_CONCAT из MySQL в 1С?

Шаблон замены: запрос с детальными строками и сортировкой по ключу группы, затем обход выборки с накоплением значений в массив и склейка через СтрСоединить при смене ключа. Либо обход результата по группировкам с ИТОГИ ПО.

Как склеить строки с разделителем-переносом строки?

Передайте в СтрСоединить разделитель Символы.ПС, например: СтрСоединить(Части, Символы.ПС). В табличном документе ячейка с такой строкой отобразит переносы, если включён режим переноса текста.

Как убрать дубликаты из склеенной строки?

Перед добавлением в массив проверяйте наличие значения: Если Части.Найти(Значение) = Неопределено Тогда Части.Добавить(Значение). На больших объёмах быстрее использовать Соответствие как множество уникальных значений, а затем выгрузить ключи.

Почему склейка работает медленно на больших документах?

Чаще всего причина в конкатенации строк операцией «+» внутри цикла — каждая итерация создаёт новую строку в памяти. Замените накоплением в массив и одним вызовом СтрСоединить. Также проверьте, что запрос не выбирает лишние поля и не дублирует строки из-за лишних соединений.

Можно ли склеить строки в динамическом списке?

Напрямую нет: динамический список отображает результат запроса построчно. Обходной путь — добавить в запрос вычисляемое поле через соединение с заранее подготовленной таблицей склеенных значений, но на практике проще выводить такую колонку в отчёте, а не в динамическом списке.

Итог

Что важно запомнить

Прямой склейки строк группы в запросе 1С нет. Рабочая схема: запрос с сортировкой по ключу группы → обход выборки → накопление значений в массив → СтрСоединить с нужным разделителем. Не забывайте обработать последнюю группу, убрать дубли и не склеивать строки операцией «+» в цикле.