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