Как отобрать в запросе элементы справочника, не имеющие родителя, и исключить группы?

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

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

Решение 1: Отбор по пустому родителю

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

Самый правильный и эффективный способ — использование конструкции ЗНАЧЕНИЕ(...). Это позволяет платформе жестко типизировать значение на этапе компиляции запроса и оптимизировать план выполнения в СУБД. Проанализируем пример кода:


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

В данном примере мы явно указываем, что нас интересуют только те записи, где поле Родитель соответствует пустому значению данного конкретного справочника. Также допустимо передавать пустую ссылку через параметр, например ГДЕ Родитель = &ПустаяСсылка, предварительно установив значение параметра в коде 1С. Однако использование ЗНАЧЕНИЕ считается более «чистым» стилем в разработке запросов, если тип ссылки заранее известен.

Решение 2: Исключение групп из выборки

Если справочник имеет тип иерархии «Группы и элементы», то при выполнении предыдущего запроса в выборку попадут не только конечные элементы, но и все папки, находящиеся в корне. Чтобы оставить только элементы, необходимо добавить дополнительное условие по булеву полю ЭтоГруппа. Разберем, как это выглядит в итоговом запросе:


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

Выясним причину использования оператора НЕ. Поле ЭтоГруппа имеет тип Булево. Если условие Автоработы.ЭтоГруппа истинно, значит, перед нами папка. Применяя отрицание НЕ, мы оставляем в результате только те записи, которые папками не являются. В современных стандартах разработки 1С также часто встречается явное сравнение ГДЕ Автоработы.ЭтоГруппа = ЛОЖЬ — оба варианта идентичны по результату.

Различие между NULL и пустой ссылкой в запросах

Важно понимать фундаментальное различие между значениями NULL и пустой ссылкой, так как начинающие разработчики часто пытаются использовать конструкцию ЕСТЬ NULL для поиска пустых родителей. Проанализируем ситуацию:

  1. Пустая ссылка — это реальное значение (бинарный ноль в базе данных), которое имеет определенный тип (например, СправочникСсылка.Автоработы). Оно хранится в таблице справочника, если родитель не выбран.
  2. NULL — это отсутствие данных как таковых. В контексте обычного запроса к одной таблице справочника поле Родитель никогда не будет равно NULL. Это значение появляется только при использовании ЛЕВОЕ СОЕДИНЕНИЕ, когда в правой таблице не находится соответствующая запись.

Следовательно, для отбора в корне справочника всегда используем сравнение с пустой ссылкой, а не проверку на NULL.

Альтернативный метод: Использование функции УРОВЕНЬ()

Рассмотрим еще один интересный способ отбора элементов верхнего уровня. В языке запросов 1С существует системная функция УРОВЕНЬ(), которая возвращает числовое значение вложенности элемента в иерархии. Для элементов и групп, находящихся в самом корне, уровень всегда равен 0.

Посмотрим на пример реализации:


ВЫБРАТЬ
    Автоработы.Ссылка
ИЗ
    Справочник.Автоработы КАК Автоработы
ГДЕ
    Автоработы.Уровень() = 0
    И НЕ Автоработы.ЭтоГруппа

Этот подход выглядит лаконично и сразу дает понять, что мы работаем с «верхним эшелоном» справочника. Однако стоит помнить, что использование функций в условии ГДЕ иногда может влиять на использование индексов, хотя в случае с иерархией платформа 1С обычно хорошо оптимизирует такие вызовы.

Оптимизация и производительность

Проанализируем вопрос производительности. Поле Родитель во всех стандартных справочниках 1С индексируется автоматически. Это означает, что отбор Родитель = &Параметр или Родитель = ЗНАЧЕНИЕ(...) будет выполняться крайне быстро даже в справочниках с миллионами записей. СУБД мгновенно находит нужные строки, не сканируя всю таблицу целиком.

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

Подводя итог, можно сказать, что наиболее универсальным и производительным способом для отбора элементов «вне папок» является совмещение проверки Родитель = ЗНАЧЕНИЕ(Справочник.Имя.ПустаяСсылка) и условия ЭтоГруппа = ЛОЖЬ. Это гарантирует точность результата и высокую скорость работы системы.

← На главную