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