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

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

При работе с запросами в системе «1С:Предприятие 8» начинающие разработчики часто сталкиваются с ситуацией, когда привычные методы встроенного языка не работают внутри текста запроса. Типичный пример — попытка получить уровень вложенности справочника или собрать «красивый» путь из наименований родителей прямо в SQL-выборке. Разберем подробно, почему возникают ошибки в таких конструкциях и как правильно реализовать задачу формирования иерархического пути.

Анализ исходной проблемы

Рассмотрим ситуацию, когда разработчик пытается использовать в запросе следующий код:


ВЫБОР 
    КОГДА (СпрНоменклатура.Ссылка.Уровень > 1) ТОГДА
        СпрНоменклатура.Родитель.Родитель + " / " + СпрНоменклатура.Родитель
    ИНАЧЕ
        СпрНоменклатура.Родитель
КОНЕЦ КАК Путь

При выполнении этого кода система выдаст синтаксическую ошибку. Здесь скрыты сразу две фундаментальные проблемы языка запросов 1С, которые мы разберем далее.

Проблема №1: Метод Уровень() в запросах

Первое, что важно понять: язык запросов 1С — это не встроенный язык системы. Это декларативный язык, который трансформируется платформой в SQL-запрос к базе данных. В таблицах SQL физически не хранится поле «Уровень».

Функция Уровень() является методом объекта (например, СправочникОбъект) или строки дерева значений. В запросе к ней обратиться нельзя. Чтобы определить вложенность элемента в запросе, мы должны использовать логические проверки наличия родителей. Если Родитель пустой — это первый уровень. Если Родитель.Родитель пустой — это второй уровень, и так далее.

Проблема №2: Конкатенация ссылок и строк

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

Для объединения строк в запросе необходимо обращаться именно к строковым полям, таким как Наименование или Код.

Правильная реализация формирования пути

Рассмотрим решение, которое позволяет обойти эти ограничения. Мы будем использовать конструкцию ВЫБОР КОГДА для проверки иерархии и обращаться к полю Наименование для формирования текстового пути.


ВЫБРАТЬ
    СпрНоменклатура.Ссылка КАК Ссылка,
    ВЫБОР
        КОГДА СпрНоменклатура.Родитель = ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)
            ТОГДА ""
        КОГДА СпрНоменклатура.Родитель.Родитель = ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)
            ТОГДА СпрНоменклатура.Родитель.Наименование
        ИНАЧЕ СпрНоменклатура.Родитель.Родитель.Наименование + " / " + СпрНоменклатура.Родитель.Наименование
    КОНЕЦ КАК Путь
ИЗ
    Справочник.Номенклатура КАК СпрНоменклатура

В этом примере мы проанализировали ситуацию по шагам:

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

Важные нюансы работы со строками в запросах

Проанализируем дополнительные возможности и ограничения, которые помогут сделать ваши запросы более надежными:

1. Использование функции ВЫРАЗИТЬ. Если вы работаете с полями неограниченной длины или хотите гарантировать определенный тип, используйте ВЫРАЗИТЬ(Поле КАК СТРОКА(100)). Это особенно актуально при конкатенации, так как СУБД может накладывать ограничения на длину результирующей строки.

2. Производительность «точечной» навигации. Помните, что каждое обращение через точку в запросе (например, Родитель.Родитель.Наименование) заставляет платформу создавать дополнительное левое соединение (LEFT JOIN) в SQL-запросе. Если у вас справочник с иерархией в 10 уровней, и вы попытаетесь собрать их все через точки, запрос может начать существенно «тормозить».

3. Функция ПРЕДСТАВЛЕНИЕ. Если вам нужно просто вывести текстовое описание ссылки в отчет, можно использовать ПРЕДСТАВЛЕНИЕ(СпрНоменклатура.Родитель). Однако помните: результат этой функции нельзя использовать внутри ВЫБОР КОГДА или складывать с другими строками в самом запросе. Эта функция вычисляется платформой уже при получении данных из БД.

Альтернативный подход: Система компоновки данных (СКД)

Выясним причину, почему иногда лучше не писать сложные конструкции ВЫБОР вручную. Если ваша задача — вывести иерархию в отчете, лучше воспользоваться возможностями СКД. В настройках системы компоновки можно указать тип вывода «Иерархия», и платформа сама построит дерево любой вложенности, избавив вас от необходимости высчитывать уровни в тексте запроса.

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

Таким образом, для успешного решения задачи всегда разделяйте возможности объектной модели 1С и языка запросов. Используйте Наименование для строк, ЗНАЧЕНИЕ(...) для проверки пустых ссылок и не забывайте о типизации данных при сложении строк.

← На главную