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

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

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

Как объединить строки в запросе 1С: оператор «+», ПОДСТРОКА, ВЫРАЗИТЬ, работа с NULL и объединение строк после запроса. Примеры кода и типичные ошибки.

Объединение строк — одна из самых частых задач при написании запросов в 1С: нужно собрать ФИО из трёх полей, склеить артикул с наименованием, сформировать представление адреса. В языке запросов 1С для этого используется оператор «+», а не функция CONCAT, как в классическом SQL. У этого подхода есть особенности: строгая типизация, чувствительность к NULL и ограничения на длину результата.

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

Ниже разобраны оба сценария с примерами кода, ограничениями платформы и типичными ошибками, которые приводят к пустым строкам или ошибкам исполнения запроса.

Оператор «+» — основной способ склеить строки в запросе

В языке запросов 1С нет функции CONCAT. Конкатенация выполняется бинарным оператором «+», который для строковых операндов работает как склейка. Пример — сборка полного наименования контрагента:

ВЫБРАТЬ

Контрагенты.Наименование + " (" + Контрагенты.ИНН + ")" КАК Представление

ИЗ

Справочник.Контрагенты КАК Контрагенты

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

Склеивать можно любое количество частей, но помните: каждая часть должна иметь строковый тип. Если хотя бы один операнд — число, дата или ссылка, запрос завершится с ошибкой «Несовместимые типы» либо вернёт неожиданный результат в зависимости от контекста.

bsl
ВЫБРАТЬ
	Сотрудники.Фамилия + " " + Сотрудники.Имя + " " + Сотрудники.Отчество КАК ФИО
ИЗ
	Справочник.Сотрудники КАК Сотрудники
ГДЕ
	НЕ Сотрудники.ПометкаУдаления

Приведение типов: ВЫРАЗИТЬ и ПОДСТРОКА

Число или дату нельзя напрямую склеить со строкой. В языке запросов нет функции явного преобразования числа в строку, поэтому на практике применяют два подхода. Первый — использовать ВЫРАЗИТЬ(Поле КАК Строка(Длина)), который работает для строковых полей составного типа, но не превращает число в строку. Второй, более надёжный — выполнить конкатенацию уже после запроса, в обходе выборки, где доступна функция Строка() и форматирование через Формат().

Функция ПОДСТРОКА(Строка, НачальнаяПозиция, Длина) позволяет взять часть поля перед склейкой — например, первые буквы имени и отчества для инициалов:

ВЫБРАТЬ

Сотрудники.Фамилия + " "

+ ПОДСТРОКА(Сотрудники.Имя, 1, 1) + "."

+ ПОДСТРОКА(Сотрудники.Отчество, 1, 1) + "." КАК ФИОКратко

ИЗ

Справочник.Сотрудники КАК Сотрудники

Учтите, что ПОДСТРОКА нумерует символы с единицы, а не с нуля. Если поле короче указанной начальной позиции, результатом будет пустая строка — ошибки не возникнет, но и данные «молча» пропадут.

Проблема NULL: почему результат склейки внезапно пустой

Если любой из операндов оператора «+» имеет значение NULL, результат всей конкатенации тоже будет NULL. При выводе в отчёт это выглядит как пустая ячейка, хотя часть данных в полях есть. Типичная ситуация — левое соединение, где у части основных записей нет связанных данных:

ВЫБРАТЬ

Заказы.Номер,

ЕСТЬNULL(Контрагенты.Наименование, "Контрагент не указан")

+ " / " + Заказы.Комментарий КАК Описание

ИЗ

Документ.ЗаказПокупателя КАК Заказы

ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Контрагенты

ПО Заказы.Контрагент = Контрагенты.Ссылка

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

Объединение значений из разных строк выборки

Задача «собрать в одну ячейку список товаров по документу» — это агрегация строк, и в языке запросов 1С прямого аналога GROUP_CONCAT нет. Стандартное решение: запрос с итогами или сортировкой по группирующему полю, затем обход выборки на встроенном языке со склейкой через массив и СтрСоединить():

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

"ВЫБРАТЬ

| Товары.Ссылка КАК Заказ,

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

|ИЗ

| Документ.ЗаказПокупателя.Товары КАК Товары

|ИТОГИ ПО

| Товары.Ссылка";

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

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

СписокТоваров = Новый Массив;

ВыборкаТовары = ВыборкаЗаказы.Выбрать();

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

СписокТоваров.Добавить(ВыборкаТовары.Товар);

КонецЦикла;

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

КонецЦикла;

Использование массива и СтрСоединить() предпочтительнее накопления через «Строка = Строка + ", " + Товар»: не приходится отдельно обрезать лишний разделитель в начале или конце, а код легче читается. На больших выборках такой подход также работает стабильнее, чем многократная конкатенация длинной строки в цикле.

Порядок действий
  1. 1
    Сформулируйте запрос с группировкой или итогами по ключевому полю
  2. 2
    Выполните обход выборки по группировкам
  3. 3
    Внутри каждой группы соберите значения в массив
  4. 4
    Склейте массив через СтрСоединить() с нужным разделителем
  5. 5
    Проверьте результат на документе с одной строкой и с пустой табличной частью

Склейка строк в СКД и в динамических списках

В системе компоновки данных конкатенацию можно выполнять на уровне выражения вычисляемого поля: там доступен тот же оператор «+» и функции языка выражений СКД. Это удобно, когда представление нужно только для отчёта и не должно попадать в сам запрос. Для вычисляемого поля укажите выражение вида Фамилия + " " + ПОДСТРОКА(Имя, 1, 1) + "." и используйте его в настройках отчёта.

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

Сравнение вариантов

Оператор «+» в запросе

Подходит для склейки полей одной записи; ограничение — все операнды должны быть строками, NULL обнуляет результат

ВЫРАЗИТЬ + ПОДСТРОКА

Для обрезки строк и работы с составными типами; не преобразует числа и даты в строку

Обход выборки + СтрСоединить()

Единственный рабочий способ склеить значения из разных строк; требует кода на встроенном языке

Вычисляемое поле СКД

Когда склейка нужна только для отчёта; не подходит для переиспользования в других запросах

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

Строковые поля в запросе имеют фиксированную длину, заданную в метаданных. При конкатенации платформа определяет длину результата автоматически, но при помещении результата во временную таблицу или при группировке по склеенному полю может произойти усечение до длины первого операнда. Если замечаете «обрезанные» значения — явно задайте длину через ВЫРАЗИТЬ(Поле1 + Поле2 КАК Строка(200)).

По производительности: конкатенация сама по себе операция дешёвая, но склеенное поле не использует индексы. Отбор вида ГДЕ Фамилия + " " + Имя = &ФИО приведёт к полному перебору таблицы. Фильтруйте по исходным полям, а склейку применяйте только в списке выбранных полей.

Типичные ошибки
01
Склейка числа со строкой без преобразования — запрос падает с ошибкой несовместимости типов
02
Игнорирование NULL в одном из полей — вся склеенная строка становится пустой
03
Отбор по склеенному полю — полный перебор таблицы и медленная работа на больших данных
04
Поиск агрегатной функции для склейки строк в запросе — её нет, задача решается обходом выборки
05
ПОДСТРОКА с позиции 0 — нумерация символов начинается с 1

Проверка результата и отладка

Быстрее всего отладить конкатенацию в консоли запросов: выполните запрос на тестовой базе и сравните склеенное поле с исходными полями, выведенными рядом. Обращайте внимание на три признака проблем: пустые значения там, где данные есть (признак NULL), обрезанные окончания строк (признак усечения длины) и отсутствие разделителей (пропущенный литерал).

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

Контрольные точки

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

Склеенное поле рядом с исходными
Норма

Все части присутствуют, разделители на месте

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

Пустая строка при заполненных исходных полях — сработал NULL

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

Строка не обрезана, даже для длинных значений

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

Окончание строки отсутствует — задайте длину через ВЫРАЗИТЬ

Скорость запроса
Норма

Отбор идёт по исходным полям, склейка только в выборке

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

Условие по склеенному полю — полный перебор таблицы

Частые вопросы

Есть ли в запросе 1С функция CONCAT или СОЕДИНИТЬ?

Нет. В языке запросов 1С конкатенация выполняется только оператором «+». Функции СтрСоединить() и СтрРазделить() существуют во встроенном языке и применяются при обходе результата запроса, но недоступны внутри текста запроса.

Как склеить число со строкой прямо в запросе?

Напрямую — никак: запрос выдаст ошибку несовместимости типов. Варианты обхода: выполнить склейку после запроса через Формат() или Строка(), либо, если число хранится в поле составного типа, попробовать ВЫРАЗИТЬ — но для чисто числовых полей это не сработает.

Как объединить значения из нескольких строк в одну ячейку отчёта?

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

Почему склеенная строка получается пустой, хотя поля заполнены?

Почти всегда причина — NULL в одном из операндов, обычно после левого соединения. Оператор «+» с любым NULL-операндом возвращает NULL. Обработайте каждое потенциально пустое поле функцией ЕСТЬNULL(Поле, "") до склейки.

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

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

Влияет ли конкатенация на скорость запроса?

Сама склейка в списке полей почти не влияет на производительность. Проблемы возникают, когда склеенное выражение используют в условии ГДЕ или соединении таблиц: индексы не применяются, и СУБД выполняет полный перебор. Держите фильтрацию на исходных полях.

Итог

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

Строки в запросе 1С склеиваются оператором «+»; все операнды должны быть строками, а NULL обнуляет результат — используйте ЕСТЬNULL. Для объединения значений из разных строк выборки применяйте обход результата и СтрСоединить(). Отборы стройте по исходным полям, а не по склеенному выражению.