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