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