Объединение строковых значений в одну строку — частая задача при работе с базами данных в 1С:Предприятие. Нужно ли сформировать список товаров через запятую, собрать адрес из отдельных полей или подготовить данные для отчёта — без грамотного объединения строк не обойтись. Однако стандартный язык запросов 1С не всегда предлагает очевидные решения для таких операций, особенно когда речь идёт о группировке данных или работе с иерархическими структурами.
В этой статье разберём 5 основных способов объединения строк в запросах 1С 8.3 и 1С 8.2: от элементарной конкатенации с помощью оператора + до сложных конструкций с использованием СКД (Система Композиции Данных) и виртуальных таблиц. Особое внимание уделим объединению строк с группировкой по полям — задаче, которая часто вызывает затруднения у разработчиков. Все примеры приведены с учётом синтаксиса последних версий платформы, но применимы и к более ранним релизам (с оговорками).
1. Простая конкатенация строк оператором "+"
Самый базовый метод — использование оператора + для склеивания строк непосредственно в тексте запроса. Подходит для случаев, когда нужно объединить фиксированное количество полей или литералов.
Пример: объединение фамилии, имени и отчества сотрудника в одно поле ФИО:
ВЫБРАТЬ
Сотрудники.Фамилия + " " + Сотрудники.Имя + " " + Сотрудники.Отчество КАК ФИО
ИЗ
Справочник.Сотрудники КАК Сотрудники
- ✅ Плюсы: максимальная простота, не требует дополнительных функций.
- ❌ Минусы: не обрабатывает значения
NULL(если одно из полей пустое, результат может быть некорректным). - ⚠️ Нюанс: для избежания пробелов в начале/конце результата используйте
СокрЛП().
Чтобы исключить пробелы при пустых значениях, модифицируем запрос:
ВЫБРАТЬ
СокрЛП(Сотрудники.Фамилия + " " + Сотрудники.Имя + " " + Сотрудники.Отчество) КАК ФИО
ИЗ
Справочник.Сотрудники КАК Сотрудники
Если в результате конкатенации получаются лишние пробелы, используйте функцию СокрЛП() — она удаляет все пробелы в начале и конце строки, а также сокращает множественные пробелы внутри до одного.
2. Функции СтрСокрЛП() и СтрЗаменить() для обработки строк
Для более гибкой обработки строк в запросах 1С предусмотрены встроенные функции:
СтрСокрЛП(Строка)— удаляет пробелы в начале и конце строки, а также заменяет множественные пробелы внутри на одиночные.СтрЗаменить(Строка, Что, НаЧто)— заменяет все вхождения подстрокиЧтонаНаЧто.
Пример использования СтрЗаменить() для форматирования телефонного номера:
ВЫБРАТЬ
СтрЗаменить(
СтрЗаменить(
Контрагенты.Телефон,
" ",
""
),
"-",
""
) КАК ТелефонБезФорматирования
ИЗ
Справочник.Контрагенты КАК Контрагенты
А вот как с помощью СтрСокрЛП() можно "очистить" адрес от лишних пробелов:
ВЫБРАТЬ
СтрСокрЛП(
Контрагенты.ПочтовыйИндекс + " " +
Контрагенты.Город + ", " +
Контрагенты.Улица + ", " +
Контрагенты.Дом
) КАК Адрес
ИЗ
Справочник.Контрагенты КАК Контрагенты
3. Объединение строк с группировкой (CONCAT в 1С)
Одна из самых востребованных задач — объединение строк с группировкой по какому-либо полю. Например, получить список всех товаров в заказе через запятую или перечень документов по контрагенту. В стандартном языке запросов 1С нет аналога GROUP_CONCAT из SQL, но эту проблему можно решить несколькими способами.
Способ 1: Использование временных таблиц
Алгоритм:
- Создать временную таблицу с нужными данными.
- Пройти по ней в цикле на встроенном языке, объединяя строки.
Пример кода (в модуле отчёта или обработки):
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЗаказыПокупателей.Контрагент КАК Контрагент,
| ЗаказыПокупателей.Номер КАК НомерЗаказа
|ИЗ
| Документ.ЗаказПокупателя КАК ЗаказыПокупателей
|ГДЕ
| ЗаказыПокупателей.Дата >= &ДатаНачала
|УПОРЯДОЧИТЬ ПО
| Контрагент";
Запрос.УстановитьПараметр("ДатаНачала", НачалоДня(ТекущаяДата()));
РезультатЗапроса = Запрос.Выполнить();
// Создаём таблицу значений для группировки
ТаблицаГруппировки = Новый ТаблицаЗначений;
ТаблицаГруппировки.Колонки.Добавить("Контрагент");
ТаблицаГруппировки.Колонки.Добавить("СписокЗаказов");
// Проходим по результату и объединяем номера заказов
ТекущийКонтрагент = "";
СписокЗаказов = "";
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
Если ТекущийКонтрагент <> Выборка.Контрагент Тогда
Если ТекущийКонтрагент <> "" Тогда
СтрокаГруппировки = ТаблицаГруппировки.Добавить();
СтрокаГруппировки.Контрагент = ТекущийКонтрагент;
СтрокаГруппировки.СписокЗаказов = Лев(СписокЗаказов, СтрДлина(СписокЗаказов) - 2); // Убираем последнюю запятую
КонецЕсли;
ТекущийКонтрагент = Выборка.Контрагент;
СписокЗаказов = "";
КонецЕсли;
СписокЗаказов = СписокЗаказов + Выборка.НомерЗаказа + ", ";
КонецЦикла;
// Добавляем последнюю группу
Если ТекущийКонтрагент <> "" Тогда
СтрокаГруппировки = ТаблицаГруппировки.Добавить();
СтрокаГруппировки.Контрагент = ТекущийКонтрагент;
СтрокаГруппировки.СписокЗаказов = Лев(СписокЗаказов, СтрДлина(СписокЗаказов) - 2);
КонецЕсли;
Способ 2: Использование СКД (Система Композиции Данных)
СКД позволяет гибко настраивать вывод данных, включая объединение строк. Для этого:
- Создайте схему компоновки данных.
- В настройках группы укажите параметр
Объединение. - Задайте разделитель (например, запятую).
Пример настройки в конструкторе СКД:
&НаСервере
Процедура СформироватьОтчет(Отчет, ПараметрыОтчета)
СхемаКомпозиции = Новый СхемаКомпоновкиДанных;
НастройкиКомпозиции = СхемаКомпозиции.НастройкиПоУмолчанию;
// Настраиваем группировку и объединение
ГруппаКонтрагентов = НастройкиКомпозиции.Группировки.Добавить();
ГруппаКонтрагентов.Поле = Новый ПолеКомпоновкиДанных("Контрагент");
ГруппаКонтрагентов.Объединение = Истина;
ГруппаКонтрагентов.Разделитель = ", ";
// Добавляем поле для объединения
ПолеЗаказы = НастройкиКомпозиции.Поля.Добавить();
ПолеЗаказы.Поле = Новый ПолеКомпоновкиДанных("НомерЗаказа");
ПолеЗаказы.Объединение = Истина;
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
Макет = КомпоновщикМакета.Выполнить(СхемаКомпозиции, НастройкиКомпозиции);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(Макет);
// Выполняем запрос и передаём данные в обработчик
РезультатЗапроса = ПолучитьДанныеДляОтчета(ПараметрыОтчета);
ПроцессорКомпоновки.ОбработатьРезультат(РезультатЗапроса);
Отчет.Макет = ПроцессорКомпоновки.ПолучитьМакет("Основной");
КонецПроцедуры
Почему СКД может работать медленнее временных таблиц?
СКД выполняет дополнительные операции по формированию макета и компоновке данных, тогда как работа с временными таблицами на встроенном языке происходит "в лоб" и часто быстрее для больших объёмов данных. Однако СКД даёт больше возможностей для форматирования и визуализации результата.
4. Виртуальные таблицы и объединение данных
В некоторых случаях для объединения строк удобно использовать виртуальные таблицы, особенно если данные нужно агрегировать по нескольким измерениям. Например, виртуальная таблица Документ.ЗаказПокупателя.СписокНоменклатуры позволяет получить все товары по заказу, а затем объединить их названия.
Пример запроса с виртуальной таблицей:
ВЫБРАТЬ
Заказы.Номер КАК НомерЗаказа,
СтрСокрЛП(
ВЫРАЗИТЬ(
МАКСИМУМ(
ВЫБОР
КОГДА Заказы.Номер = Товары.Ссылка.Номер
ТОГДА Товары.Номенклатура.Наименование + ", "
ИНАЧЕ ""
КОНЕЦ
) КАК Строка
) КАК Строка
) КАК СписокТоваров
ИЗ
Документ.ЗаказПокупателя КАК Заказы
ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказПокупателя.СписокНоменклатуры КАК Товары
ПО Заказы.Ссылка = Товары.Ссылка
СГРУППИРОВАТЬ ПО
Заказы.Номер
⚠️ Внимание: Виртуальные таблицы могут значительно увеличивать нагрузку на сервер, особенно при работе с большими документами (например, заказами с тысячами строк номенклатуры). Перед использованием оценивайте объём данных!
| Метод объединения | Сложность реализации | Производительность | Когда использовать |
|---|---|---|---|
Оператор + |
Низкая | Высокая | Простая конкатенация без группировки |
Функции СтрСокрЛП(), СтрЗаменить() |
Низкая | Высокая | Форматирование строк, удаление пробелов |
| Временные таблицы + цикл | Средняя | Средняя | Группировка с объединением (например, списки заказов по контрагенту) |
| СКД (Система Композиции Данных) | Высокая | Низкая | Сложные отчёты с визуализацией |
| Виртуальные таблицы | Средняя | Низкая | Агрегация данных по документам |
5. Использование внешних функций и расширений
Если стандартные средства 1С не покрывают ваши нужды (например, требуется сложное форматирование или работа с большими объёмами данных), можно воспользоваться:
- ⚡ Внешними компонентами (например, 1Script или OneScript для расширенной обработки строк).
- 📦 Готовыми расширениями из каталога 1С:Галлерея решений (например, для экспорта данных в Excel с объединёнными ячейками).
- 🔧 SQL-запросами (если база данных поддерживает
GROUP_CONCATили аналогичные функции).
Пример использования GROUP_CONCAT в PostgreSQL (если 1С работает с этой СУБД):
ВЫБРАТЬ
Контрагенты.Наименование КАК Контрагент,
ВЫРАЗИТЬ(
ВНЕШНИЙ_ЗАПРОС(
"SELECT string_agg(заказы.номер, ', ')
FROM заказы
WHERE заказы.контрагент_id = контрагенты.id"
) КАК Строка
) КАК СписокЗаказов
ИЗ
Справочник.Контрагенты КАК Контрагенты
⚠️ Внимание: Использование внешних компонент и прямых SQL-запросов может нарушить поддержку типовой конфигурации и усложнить обновления. Применяйте такие методы только в крайних случаях и документируйте изменения!
6. Типичные ошибки и как их избежать
При объединении строк в запросах 1С разработчики часто сталкиваются с следующими проблемами:
- 🔴 Пустые значения (
NULL): если одно из полей пустое, оператор+может вернуть неожиданный результат. Всегда проверяйте значения наЗначениеЗаполнено()или используйтеВЫРАЗИТЬ(... КАК Строка). - 🔴 Переполнение строки: в 1С длина строки ограничена ~4 ГБ, но на практике при объединении тысяч значений может возникнуть ошибка. В таких случаях разделяйте данные на части.
- 🔴 Неправильные разделители: забытые запятые или пробелы в конце строки портят форматирование. Используйте
Лев(Строка, СтрДлина(Строка) - 2)для удаления последнего разделителя. - 🔴 Производительность: объединение большого количества строк в цикле может тормозить систему. Для критичных операций используйте временные таблицы в SQL.
Пример обработки NULL:
ВЫБРАТЬ
ВЫРАЗИТЬ(Сотрудники.Отчество КАК Строка) КАК ОтчествоБезNULL
ИЗ
Справочник.Сотрудники КАК Сотрудники
Исключены пустые значения (NULL)|Учтена максимальная длина результирующей строки|Правильно обработаны разделители (запятые, пробелы)|Оптимизирован запрос для больших объёмов данных-->
FAQ: Частые вопросы по объединению строк в 1С
Как объединить строки с переносом строки (символом новой строки)?
Используйте функцию Символы.ПС (перенос строки) в качестве разделителя:
СтрЗаменить(СписокСтрок, ", ", Символы.ПС)
Для вывода в отчёт настройте параметр МногострочныйРежим в поле компоновки данных.
Можно ли объединить строки без использования временных таблиц?
Да, для простых случаев подходит оператор + или функции СтрСокрЛП(). Однако для группировки с объединением (аналог GROUP_CONCAT) без временных таблиц или СКД не обойтись.
Почему при объединении строк в СКД пропали некоторые значения?
Проверьте:
- Настройки группировки в схеме компоновки (возможно, не все поля включены в объединение).
- Фильтры в отчёте — некоторые строки могли быть исключены.
- Параметр
Объединениедля поля — он должен быть установлен вИстина.
Как объединить строки с учётом иерархии (например, номенклатура → характеристики)?
Для иерархических данных используйте рекурсивные запросы или виртуальные таблицы с предопределёнными данными. Пример для номенклатуры с характеристиками:
ВЫБРАТЬ
Номенклатура.Наименование КАК Номенклатура,
СтрСокрЛП(
ВЫБОР
КОГДА Характеристики.Наименование <> ""
ТОГДА Характеристики.Наименование
ИНАЧЕ ""
КОНЕЦ
) КАК Характеристики
ИЗ
Справочник.Номенклатура КАК Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ХарактеристикиНоменклатуры КАК Характеристики
ПО Номенклатура.Ссылка = Характеристики.Номенклатура
Есть ли ограничения на длину результирующей строки при объединении?
Теоретический предел — около 4 ГБ (максимальный размер строки в 1С). Однако на практике:
- При выводе в отчёт СКД может обрезать длинные строки.
- В временных таблицах ограничение зависит от настроек СУБД.
- Для SQL Server и PostgreSQL максимальная длина результата
GROUP_CONCATнастраивается отдельно.
Если строка превышает 1000 символов, разделяйте её на части или выгружайте в файл.
Для большинства задач по объединению строк в 1С достаточно комбинации оператора +, функций СтрСокрЛП()/СтрЗаменить() и временных таблиц. СКД удобна для отчётов, но проигрывает в производительности при больших объёмах данных.