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