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

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

При разработке отчетов и доработке конфигураций на базе типовых решений (БСП) часто возникает задача отобрать документы по дополнительному реквизиту, созданному пользователями в режиме 1С:Предприятие. Поскольку такие реквизиты отсутствуют в составе реквизитов шапки документа в дереве метаданных, прямое обращение через точку вида ЗаказКлиента.МойДопРеквизит в тексте запроса невозможно.

Разберем по шагам, где физически хранятся дополнительные реквизиты, почему простой отбор по массиву строк не возвращает данные и как правильно составить запрос к базе данных.

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

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

Рассмотрим структуру колонок этой табличной части:

  1. Свойство — ссылка на план видов характеристик ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения, определяющая сам реквизит.
  2. Значение — составной тип данных, содержащий выбранное значение (для списков выбора это ссылки на справочник Справочник.ЗначенияСвойствОбъектов или Справочник.ЗначенияСвойствОбъектовИерархия).
  3. ТекстоваяСтрока — строковое поле, используемое для хранения произвольного текста, если реквизит имеет строковый тип большой длины.

Выясним причину: почему отбор по значению не возвращает строки

Типичная ошибка при составлении запроса — передача в параметр условия Значение В (&Источник) массива обычных строк (текстовых наименований). Проанализируем, почему выборка получается пустой:

  1. Несоответствие типов: Если дополнительный реквизит имеет тип «Дополнительное значение» (выпадающий список), поле Значение содержит ссылку на справочник ЗначенияСвойствОбъектов, а не строку. Сравнение ссылки со строкой всегда возвращает ЛОЖЬ.
  2. Отсутствие отбора по свойству: Табличная часть ДополнительныеРеквизиты хранит все дополнительные реквизиты документа. Если не ограничить выборку конкретным свойством, отбор будет производиться по всем строкам таблицы, что может привести к некорректным результатам.
  3. Задвоение строк: Простое левое соединение с табличной частью при наличии нескольких строк дополнительных реквизитов может дублировать строки документа в выборке.

Решение 1. Подготовка ссылочных параметров и составление запроса

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

Шаг 1. Получение ссылок на свойство и его значения в коде:

Перед выполнением основного запроса найдем ссылку на само свойство и получим массив ссылок на выбранные значения справочника ЗначенияСвойствОбъектов:


// 1. Находим свойство по наименованию или имени для разработчиков
Свойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Вид доставки");

Если Не ЗначениеЗаполнено(Свойство) Тогда
    ВызватьИсключение "Дополнительный реквизит не найден в информационной базе!";
КонецЕсли;

// 2. Получаем ссылки на значения свойства по их текстовым наименованиям
МассивНаименований = Новый Массив;
МассивНаименований.Добавить("Курьер");
МассивНаименований.Добавить("Самовывоз");

ЗапросЗначений = Новый Запрос;
ЗапросЗначений.Текст = 
    "ВЫБРАТЬ
    |	Значения.Ссылка КАК Ссылка
    |ИЗ
    |	Справочник.ЗначенияСвойствОбъектов КАК Значения
    |ГДЕ
    |	Значения.Владелец = &Свойство
    |	И Значения.Наименование В(&МассивНаименований)";

ЗапросЗначений.УстановитьПараметр("Свойство", Свойство);
ЗапросЗначений.УстановитьПараметр("МассивНаименований", МассивНаименований);

СписокСсылок = ЗапросЗначений.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка");

Шаг 2. Выполнение запроса к документам через вложенный запрос:

Чтобы избежать дублирования строк документа и получить корректную выборку, используем условие В (ВЫБРАТЬ ...):


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Заказ.Ссылка КАК Ссылка,
    |	Заказ.Номер КАК Номер,
    |	Заказ.Дата КАК Дата,
    |	Заказ.СуммаДокумента КАК Сумма
    |ИЗ
    |	Документ.ЗаказКлиента КАК Заказ
    |ГДЕ
    |	Заказ.Дата МЕЖДУ &НачДата И &КонДата
    |	И Заказ.Ссылка В
    |		(ВЫБРАТЬ
    |			ДопРеквизиты.Ссылка
    |		ИЗ
    |			Документ.ЗаказКлиента.ДополнительныеРеквизиты КАК ДопРеквизиты
    |		ГДЕ
    |			ДопРеквизиты.Свойство = &Свойство
    |			И ДопРеквизиты.Значение В(&СписокСсылок))";

Запрос.УстановитьПараметр("НачДата", НачалоДня(ТекущаяДата()));
Запрос.УстановитьПараметр("КонДата", КонецДня(ТекущаяДата()));
Запрос.УстановитьПараметр("Свойство", Свойство);
Запрос.УстановитьПараметр("СписокСсылок", СписокСсылок);

Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
    // Обработка отобранных документов
КонецЦикла;

Решение 2. Выборка значения свойства через прямое соединение

Если в результат запроса необходимо вывести само значение дополнительного реквизита, используем ЛЕВОЕ СОЕДИНЕНИЕ, обязательно указывая условие по конкретному свойству в секции ПО:


ВЫБРАТЬ
	Заказ.Ссылка КАК Ссылка,
	Заказ.Номер КАК Номер,
	Заказ.Дата КАК Дата,
	ДопРеквизиты.Значение КАК ЗначениеРеквизита
ИЗ
	Документ.ЗаказКлиента КАК Заказ
	ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказКлиента.ДополнительныеРеквизиты КАК ДопРеквизиты
		ПО Заказ.Ссылка = ДопРеквизиты.Ссылка
		И ДопРеквизиты.Свойство = &Свойство
ГДЕ
	Заказ.Дата МЕЖДУ &НачДата И &КонДата
	И ДопРеквизиты.Значение В(&СписокСсылок)

Решение 3. Использование механизма характеристик в СКД

Если выборка строится в рамках отчета на Системе компоновки данных (СКД), связывать табличные части вручную не требуется. Рассмотрим настройку характеристик:

  1. В схеме компоновки данных перейдем на вкладку Характеристики.
  2. Добавим новую строку для объекта Документ.ЗаказКлиента.
  3. Укажем параметры:
    • Виды характеристик: ПланВидовХарактеристик.ДополнительныеРеквизитыИСведения;
    • Таблица характеристик: Документ.ЗаказКлиента.ДополнительныеРеквизиты;
    • Поле объекта: Ссылка;
    • Поле вида: Свойство;
    • Поле значения: Значение.

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

← На главную