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

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

В практике разработки на платформе 1С часто возникает задача, когда необходимо сгруппировать данные и объединить текстовые значения из нескольких строк в одну — для этого подойдёт обработка формирования текста из реквизитов документа. Типичный пример: для одного заказа существует несколько реализаций, и в отчете нужно вывести их номера через запятую в одной ячейке. Стандартный язык запросов 1С не имеет прямой функции типа GROUP_CONCAT или STRING_AGG, как в классических СУБД, поэтому программистам приходится прибегать к различным архитектурным решениям. Рассмотрим подробнее основные способы реализации этой задачи.

Способ 1. Использование Системы компоновки данных (СКД)

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

Проанализируем шаги по настройке этого метода (упростить разработку поможет СКДБилдер — см. консоль запросов, кода и СКД для разработчика):

  1. Откроем пользовательскую схему компоновки данных и перейдем на закладку "Ресурсы".
  2. Выберем поле, которое необходимо объединить (например, НомерРеализации).
  3. В колонке "Выражение" укажем конструкцию: СоединитьСтроки(НомерРеализации, "; ").
  4. В колонке "Рассчитывать по..." укажем те группировки, в рамках которых нужно склеивать строки (например, по полю Заказ).

Этот метод работает на уровне обработки результата запроса самой компоновкой, что избавляет нас от необходимости писать сложные вложенные циклы или перегружать SQL-сервер сложными соединениями. Рассмотрим пример выражения:


// В поле "Выражение" на закладке Ресурсы СКД
СоединитьСтроки(ТаблицаРеализаций.НомерДокумента, ", ", "Сортировать по ДатаДокумента")

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

Способ 2. Алгоритм «Бинарного дерева» в тексте запроса

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

Суть алгоритма заключается в том, что мы нумеруем строки внутри каждой группы, а затем соединяем таблицу саму с собой, увеличивая шаг смещения в геометрической прогрессии (1, 2, 4, 8, 16...). Посмотрим на упрощенную логику построения такого запроса:

  1. Создаем временную таблицу с данными и порядковым номером.
  2. Выполняем левое соединение таблицы к самой себе по условию Т1.Номер = Т2.Номер - 1.
  3. На каждой итерации количество объединенных строк в одной записи удваивается.

Всего за 10 таких итераций (соединений) в запросе можно объединить до 1024 строк. Это довольно сложный в написании код, но он работает крайне быстро на стороне СУБД. Проанализируем пример фрагмента запроса для первого шага склейки:


ВЫБРАТЬ
    Т1.Заказ,
    Т1.НомерСтроки,
    Т1.Значение + ВЫБОР
        КОГДА Т2.Значение ЕСТЬ НЕ NULL
            ТОГДА "; " + Т2.Значение
        ИНАЧЕ ""
    КОНЕЦ КАК ОбъединеннаяСтрока
ИЗ
    ВТ_Данные КАК Т1
        ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Данные КАК Т2
        ПО Т1.Заказ = Т2.Заказ
            И (Т1.НомерСтроки + 1 = Т2.НомерСтроки)

Такой подход оправдан в высоконагруженных системах, где важно минимизировать количество передаваемых данных между сервером баз данных и сервером приложений 1С.

Способ 3. Программная обработка через таблицу значений и Массив

Рассмотрим наиболее гибкий способ, который выбрал автор темы — для этого подойдёт инструментарий разработчика 1С для программных алгоритмов. Если количество данных не исчисляется миллионами строк, а логика условий объединения слишком сложна (разные типы документов, возвраты, оплаты), проще всего обработать результат запроса программно.

Однако, вместо обычного перебора строк с использованием оператора +, который в цикле может работать медленно из-за особенностей выделения памяти под строки, рекомендуется использовать метод СтрСоединить(). Разберем правильный алгоритм:

  1. Выгружаем результат запроса в ТаблицаЗначений.
  2. Группируем таблицу по ключевому полю (например, Заказ).
  3. Для каждой группы собираем нужные значения в Массив.
  4. Используем СтрСоединить(ВашМассив, "; ") для получения итоговой строки.

Пример эффективного кода на встроенном языке:


Запрос = Новый Запрос("ВЫБРАТЬ Заказ, Номер ИЗ ВТ_Документы УПОРЯДОЧИТЬ ПО Заказ, Дата");
Результат = Запрос.Выполнить();

// Используем соответствие для накопления массивов по заказам
СоответствиеСтрок = Новый Соответствие;

Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
    МассивНомеров = СоответствиеСтрок.Получить(Выборка.Заказ);
    Если МассивНомеров = Неопределено Тогда
        МассивНомеров = Новый Массив;
        СоответствиеСтрок.Вставить(Выборка.Заказ, МассивНомеров);
    КонецЕсли;
    МассивНомеров.Добавить(Выборка.Номер);
КонецЦикла;

// Теперь формируем итоговую таблицу или выводим данные
Для Каждого ЗаписьИзСоответствия Из СоответствиеСтрок Цикл
    ИтоговаяСтрока = СтрСоединить(ЗаписьИзСоответствия.Значение, "; ");
    // Далее логика использования ИтоговаяСтрока
КонецЦикла;

Этот метод считается "золотой серединой": он понятен любому разработчику, легко отлаживается и работает достаточно быстро на средних объемах данных.

Особенности и ограничения

При выборе метода стоит учитывать несколько важных технических моментов. Во-первых, длина строки. В некоторых СУБД (например, при использовании устаревших версий SQL) строковые поля могут иметь ограничение в 1024 или 2048 символов при определенных операциях. Если список документов очень длинный, итоговая строка может быть обрезана.

Во-вторых, обратите внимание на тип данных. Функции конкатенации в запросе работают только со строковыми типами. Если вы пытаетесь объединить числа (суммы) или даты, их необходимо предварительно преобразовать в строку. В запросе 1С функция ПРЕДСТАВЛЕНИЕ() возвращает специальный тип, который нельзя складывать с другими строками. Поэтому преобразование типов лучше делать либо в СКД, либо программно в цикле обхода выборки.

Резюмируем: для простых отчетов используйте СКД; для сложных алгоритмов внутри запроса без возможности постобработки — метод бинарного дерева; для задач с ветвистой логикой — программный обход с методом СтрСоединить (что позволяет попутно выполнить подсчет количества слов в тексте).

← На главную