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