К статье
Практический материал

Разработка и Конфигурация · 10 мин

Условие в запросе 1С по дополнительному реквизиту

Как построить условие в запросе 1С по дополнительному реквизиту: соединение с таблицей ДополнительныеРеквизиты, отбор в СКД, типовые ошибки и примеры кода.

Дополнительные реквизиты в 1С хранятся не в основной таблице справочника или документа, а в отдельной табличной части «ДополнительныеРеквизиты», которая физически разворачивается в план видов характеристик «ДополнительныеРеквизитыИСведения». Поэтому простое обращение «Номенклатура.МойРеквизит» в запросе не сработает — платформа не видит такого поля. Чтобы наложить условие по доп реквизиту, нужно соединить основную таблицу с таблицей значений дополнительных реквизитов и отфильтровать по свойству и значению.

Задача встречается в трёх типовых сценариях: отбор в произвольном запросе отчёта, условие в СКД и программная выборка в коде. Во всех случаях логика одинакова: сначала определяем ссылку на нужное свойство в плане видов характеристик, затем соединяем таблицы и накладываем отбор по значению. Ниже — рабочие примеры для каждого сценария.

Важно понимать разницу между дополнительными реквизитами и дополнительными сведениями: реквизиты хранятся в табличной части объекта, сведения — в регистре сведений «ДополнительныеСведения». Техника соединения отличается, и путать их нельзя — запрос либо вернёт пустой результат, либо не скомпилируется.

Как устроено хранение дополнительных реквизитов

Когда пользователь добавляет дополнительный реквизит через «Администрирование → Общие настройки → Дополнительные реквизиты и сведения», платформа создаёт элемент плана видов характеристик «ДополнительныеРеквизитыИСведения». Сами значения хранятся в табличной части объекта с двумя ключевыми полями: «Свойство» (ссылка на ПВХ) и «Значение» (произвольный тип, заданный в свойстве).

Из этого следуют два практических вывода. Первый: в одном объекте может быть несколько доп реквизитов, поэтому соединение без отбора по свойству размножит строки результата. Второй: тип поля «Значение» — составной, поэтому сравнение с параметром неправильного типа может неявно не сработать, особенно при сравнении строк разной длины или чисел с разной точностью.

Базовый запрос с условием по доп реквизиту

Типовой запрос для отбора номенклатуры по значению доп реквизита выглядит так:

ВЫБРАТЬ

Номенклатура.Ссылка КАК Номенклатура,

ДопРеквизиты.Значение КАК ЗначениеРеквизита

ИЗ

Справочник.Номенклатура КАК Номенклатура

ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура.ДополнительныеРеквизиты КАК ДопРеквизиты

ПО Номенклатура.Ссылка = ДопРеквизиты.Ссылка

ГДЕ

ДопРеквизиты.Свойство = &Свойство

И ДопРеквизиты.Значение = &Значение

Параметр «Свойство» удобнее всего получать по имени свойства через запрос к плану видов характеристик или через предопределённое имя, если оно задано. Передавать ссылку «наугад» нельзя — в разных базах у одного и того же свойства будут разные ссылки.

Если нужно вывести значение реквизита, но не отсекать объекты без него, замените ВНУТРЕННЕЕ соединение на ЛЕВОЕ и перенесите условие по свойству в секцию ПО соединения, иначе левое соединение превратится во внутреннее:

ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура.ДополнительныеРеквизиты КАК ДопРеквизиты

ПО Номенклатура.Ссылка = ДопРеквизиты.Ссылка

И ДопРеквизиты.Свойство = &Свойство

Типичные ошибки
01
Условие по свойству в ГДЕ при левом соединении — объекты без реквизита пропадают из результата. Переносите условие в секцию ПО.
02
Сравнение значения строкового реквизита без учёта длины: «Значение = &Строка» не срабатывает, если типы строк разной длины. Используйте ВЫРАЗИТЬ или ПОДОБНО.
03
Отбор по наименованию свойства строкой вместо ссылки — запрос медленнее и ломается при переименовании свойства.
04
Соединение без отбора по свойству — каждая строка объекта дублируется по числу его доп реквизитов.

Как получить ссылку на свойство программно

Жёстко зашивать ссылку в код нельзя — при переносе между базами она изменится. Надёжные способы: поиск по имени, по предопределённому имени или через набор доп реквизитов. Пример поиска по заголовку:

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ ПЕРВЫЕ 1

| Свойства.Ссылка КАК Свойство

|ИЗ

| ПланВидовХарактеристик.ДополнительныеРеквизитыИСведения КАК Свойства

|ГДЕ

| Свойства.Заголовок = &Заголовок";

Запрос.УстановитьПараметр("Заголовок", "Цвет товара");

Если свойство создавалось программно или известно его имя в конфигурации, надёжнее использовать предопределённое имя или хранить ссылку в константе/параметре отчёта, заполняемом один раз при настройке. В типовых конфигурациях на БСП есть модуль «УправлениеСвойствами» (PropertyManager), который предоставляет служебные функции для работы со свойствами.

Условие по доп реквизиту в СКД

В отчётах на СКД тот же запрос помещается в набор данных, а свойство и значение выносятся в параметры. Чтобы пользователь мог сам выбирать значение в настройках отчёта, объявите параметр «Значение» доступным и снимите у него флаг «Ограничение доступности».

Более гибкий вариант — характеристики СКД. В настройках схемы на закладке «Характеристики» можно описать доп реквизиты как источник характеристик, после чего пользователь увидит их в отборах как обычные поля, без доработки запроса. Это стандартный механизм типовых конфигураций: именно так в отчётах появляются отборы вида «[Цвет товара] = Синий».

Ограничение механизма характеристик: он требует корректного описания типов и источника видов характеристик, иначе поле в отборе появится, но отбор не сработает. Проверяйте результат на тестовых данных с заполненным и пустым значением реквизита.

Сравнение вариантов

Соединение в тексте запроса

Подходит для разового отчёта и программной выборки. Минус: отбор жёстко зашит, пользователь не может менять его в настройках.

Параметры запроса в СКД

Пользователь задаёт значение в форме отчёта. Подходит, когда набор реквизитов фиксирован.

Характеристики СКД

Все доп реквизиты автоматически доступны в отборах. Лучший вариант для универсальных отчётов, но требует аккуратной настройки.

Временная таблица + отбор в коде

Когда условие сложное (несколько реквизитов, ИЛИ между ними): сначала выбираются подходящие ссылки во временную таблицу, затем основной запрос соединяется с ней.

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

Если условий несколько, соединять табличную часть нужно по одному разу на каждый реквизит, давая каждому соединению свой псевдоним:

ГДЕ

Реквизит1.Свойство = &Свойство1 И Реквизит1.Значение = &Значение1

И Реквизит2.Свойство = &Свойство2 И Реквизит2.Значение В (&СписокЗначений)

Для условия «ИЛИ» между разными реквизитами удобнее сгруппировать табличную часть: выбрать ссылки, где свойство входит в список и значение подходит, сгруппировать по ссылке и проверить количество совпадений. Для строковых значений используйте ПОДОБНО с шаблоном, но помните, что индексного поиска по «%в начале шаблона» не будет — на больших таблицах это заметно замедлит запрос.

Проверка результата и производительность

После построения запроса проверьте три вещи: количество строк (не размножились ли они из-за соединения), наличие объектов без заполненного реквизита (если используется левое соединение, они должны присутствовать с NULL) и корректность отбора по типу значения.

По производительности: табличная часть доп реквизитов индексируется по ссылке, поэтому соединение «Ссылка = Ссылка» работает быстро. Узкое место — отбор по полю «Значение»: индекса по нему нет, и на больших объёмах выгоднее сначала отобрать объекты по другим условиям во временную таблицу, а потом соединять с доп реквизитами.

Контрольные точки

Как проверить результат

Число строк результата
Норма

Совпадает с числом отобранных объектов

Тревожный признак

Строк больше — соединение без отбора по свойству

Объекты без реквизита при левом соединении
Норма

Присутствуют, значение NULL

Тревожный признак

Отсутствуют — условие по свойству стоит в ГДЕ

Отбор по строковому значению
Норма

Находит значения независимо от регистра/длины

Тревожный признак

Часть значений не находится — конфликт типов строк

Частые вопросы

Чем отличается запрос по доп реквизиту от запроса по доп сведению?

Доп реквизит хранится в табличной части объекта — соединение идёт с Справочник.Имя.ДополнительныеРеквизиты. Доп сведение хранится в регистре сведений «ДополнительныеСведения», где объект указан в поле «Объект», а соединение строится по РегистрСведений.ДополнительныеСведения с условиями по полям «Свойство» и «Значение».

Почему условие «Значение = &Параметр» не срабатывает для строки?

Поле «Значение» имеет составной тип с фиксированной длиной строки. Если параметр — строка другой длины, сравнение может не выполняться. Решение: привести значение через ВЫРАЗИТЬ(ДопРеквизиты.Значение КАК Строка(N)) или использовать ПОДОБНО.

Как отобрать объекты, у которых доп реквизит не заполнен?

Используйте левое соединение с условием по свойству в секции ПО и добавьте в ГДЕ условие «ДопРеквизиты.Значение ЕСТЬ NULL». Альтернатива — условие «НЕ Ссылка В (ВЫБРАТЬ Ссылка ИЗ табличной части ГДЕ Свойство = &Свойство)».

Можно ли использовать доп реквизит в отборе динамического списка?

Да, если список построен на произвольном запросе: добавьте соединение с табличной частью и условие в текст запроса. Учтите, что произвольный запрос с соединениями может замедлить открытие списка и отключить часть стандартных возможностей динамического списка.

Как сделать отбор по доп реквизиту в типовом отчёте без доработки?

В типовых конфигурациях на БСП доп реквизиты обычно подключены к отчётам через механизм характеристик СКД: откройте настройки отчёта, добавьте отбор и найдите поле с именем вашего реквизита в списке доступных полей. Если поля нет — отчёт не поддерживает характеристики, и потребуется доработка схемы.

Итог

Что важно запомнить

Условие по доп реквизиту строится через соединение с табличной частью «ДополнительныеРеквизиты» с отбором по свойству и значению. Условие по свойству при левом соединении помещайте в секцию ПО, ссылку на свойство получайте программно, для универсальных отчётов используйте характеристики СКД.