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