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