Как найти номенклатуру без подчиненных сертификатов в 1С?

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

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

Рассмотрим, как правильно составить запрос на языке 1С, чтобы определить, у каких позиций номенклатуры отсутствуют подчиненные сертификаты.

Решение через левое соединение и проверку на NULL

Основным и наиболее эффективным способом решения данной задачи является использование ЛЕВОГО СОЕДИНЕНИЯ двух таблиц справочников с последующей фильтрацией по условию ЕСТЬ NULL.

При левом соединении в результат попадают абсолютно все записи из левой таблицы (в нашем случае — Справочник.Номенклатура). Если для какой-то номенклатуры в правой таблице (Справочник.Сертификаты) не находится подчиненной записи по условию Номенклатура.Ссылка = Сертификаты.Владелец, то поля правой таблицы для этой строки заполняются значением NULL.

Разберем пример запроса:


ВЫБРАТЬ
	Номенклатура.Ссылка КАК Номенклатура
ИЗ
	Справочник.Номенклатура КАК Номенклатура
	ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Сертификаты КАК Сертификаты
		ПО Номенклатура.Ссылка = Сертификаты.Владелец
ГДЕ
	Сертификаты.Ссылка ЕСТЬ NULL

В этом запросе мы выбираем все элементы номенклатуры, соединяем их с сертификатами по реквизиту Владелец и оставляем только те строки, где ссылка на сертификат равна NULL. Это и означает, что у номенклатуры нет ни одного подчиненного сертификата.

Альтернативный вариант через подзапрос НЕ В

Проверить отсутствие подчиненных элементов можно и без соединения таблиц на верхнем уровне, используя условие НЕ В с подзапросом.

Посмотрим на пример реализации такого подхода:


ВЫБРАТЬ
	Номенклатура.Ссылка КАК Номенклатура
ИЗ
	Справочник.Номенклатура КАК Номенклатура
ГДЕ
	НЕ Номенклатура.Ссылка В
		(ВЫБРАТЬ РАЗЛИЧНЫЕ
			Сертификаты.Владелец
		ИЗ
			Справочник.Сертификаты КАК Сертификаты)

Этот вариант удобен, если в подзапросе требуется наложить сложную фильтрацию на подчиненную таблицу (например, отсечь сертификаты со специальными статусами или дополнительными условиями).

Учет иерархии и пометки на удаление

При применении решения в реальных конфигурациях необходимо учитывать особенности хранения данных в 1С:

  1. Исключение групп: Если справочник Номенклатура иерархический, в результат запроса попадут и папки (группы). Чтобы выбирать только элементы (товары и услуги), необходимо добавить фильтр Номенклатура.ЭтоГруппа = ЛОЖЬ.
  2. Помеченные на удаление элементы: Если сертификат помечен на удаление (ПометкаУдаления = Истина), платформа все еще хранит его в базе. Чтобы не учитывать удаленные сертификаты, условие их отсутствия или недействительности накладывают непосредственно в секции соединения.

Проанализируем усовершенствованный вариант запроса с учетом этих факторов:


ВЫБРАТЬ
	Номенклатура.Ссылка КАК Номенклатура
ИЗ
	Справочник.Номенклатура КАК Номенклатура
	ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Сертификаты КАК Сертификаты
		ПО Номенклатура.Ссылка = Сертификаты.Владелец
		И (Сертификаты.ПометкаУдаления = ЛОЖЬ)
ГДЕ
	Номенклатура.ЭтоГруппа = ЛОЖЬ
	И Номенклатура.ПометкаУдаления = ЛОЖЬ
	И Сертификаты.Ссылка ЕСТЬ NULL

Важное правило: дополнительное условие Сертификаты.ПометкаУдаления = ЛОЖЬ следует размещать именно в секции ПО (в условиях соединения). Если написать его в секции ГДЕ, левое соединение фактически превратится во внутреннее, и элементы без сертификатов вообще не попадут в выборку.

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

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

Для этого в условии соединения явно ограничивают тип с помощью функции ВЫРАЗИТЬ() или оператора ССЫЛКА:


ВЫБРАТЬ
	Номенклатура.Ссылка КАК Номенклатура
ИЗ
	Справочник.Номенклатура КАК Номенклатура
	ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Сертификаты КАК Сертификаты
		ПО Номенклатура.Ссылка = ВЫРАЗИТЬ(Сертификаты.Владелец КАК Справочник.Номенклатура)
ГДЕ
	Сертификаты.Ссылка ЕСТЬ NULL

Проверка наличия сертификата для одного элемента в коде

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


Запрос = Новый Запрос;
Запрос.Текст = 
	"ВЫБРАТЬ ПЕРВЫЕ 1
	|	Сертификаты.Ссылка КАК Ссылка
	|ИЗ
	|	Справочник.Сертификаты КАК Сертификаты
	|ГДЕ
	|	Сертификаты.Владелец = &Номенклатура
	|	И НЕ Сертификаты.ПометкаУдаления";

Запрос.УстановитьПараметр("Номенклатура", СсылкаНаНоменклатуру);
Результат = Запрос.Выполнить();

Если Результат.Пустой() Тогда
	Сообщить("У выбранной номенклатуры отсутствуют действующие сертификаты!");
КонецЕсли;

Поскольку стандартный реквизит Владелец в платформах 1С индексируется автоматически, данный запрос выполняется мгновенно даже на очень больших объемах данных.

← На главную