Как отфильтровать срез последних регистра сведений по конкретному виду цен в запросе 1С?

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

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

Ограничения языка запросов 1С: почему нельзя жестко прописать непредопределенный элемент

В языке запросов 1С существует специальная конструкция ЗНАЧЕНИЕ(), которая позволяет обращаться к предопределенным элементам конфигурации, значениям перечислений или системным типам данных напрямую в тексте запроса без передачи внешних параметров. Например, для предопределенного вида цены можно написать:


ГДЕ
    ВидЦен = ЗНАЧЕНИЕ(Справочник.ВидыЦен.Оптовая)

Однако если элементы справочника ВидыЦен созданы пользователями в режиме предприятия и не являются предопределенными в дереве метаданных конфигуратора, обратиться к ним через ЗНАЧЕНИЕ() на уровне синтаксиса платформы невозможно.

Посмотрим на основные способы получения цен по конкретному непредопределенному виду цены.

Способ 1. Передача ссылки через параметр запроса (рекомендуемый стандарт)

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

Разберем по шагам реализацию этого метода:

  1. Находим нужный элемент в модуле с помощью менеджера справочника, используя метод НайтиПоКоду(), НайтиПоНаименованию() или считываем значение из константы/настройки.
  2. Передаем найденную ссылку в параметры запроса.
  3. Устанавливаем условие строго во втором параметре виртуальной таблицы СрезПоследних.

Посмотрим на пример программного кода:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Цены.Номенклатура КАК Номенклатура,
    |	Цены.Цена КАК Цена
    |ИЗ
    |	РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ВидЦен = &НужныйВидЦен) КАК Цены";

// Поиск ссылки на элемент справочника
СсылкаВидЦены = Справочники.ВидыЦен.НайтиПоКоду("000000022");

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

РезультатЗапроса = Запрос.Выполнить();

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

Способ 2. Отбор по коду или наименованию внутри параметров виртуальной таблицы

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


ВЫБРАТЬ
	Цены.Номенклатура КАК Номенклатура,
	Цены.Цена КАК Цена
ИЗ
	РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ВидЦен.Код = "000022") КАК Цены

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

  1. Такой вариант работает без предварительного поиска ссылки во встроенном языке.
  2. Ограничение производительности: при обращении через точку (ВидЦен.Код) СУБД выполняет неявное левое соединение (LEFT JOIN) с таблицей справочника до вычисления среза последних, что на больших объемах данных увеличивает нагрузку на сервер.
  3. При изменении кода или наименования элемента пользователем в режиме предприятия запрос перестанет возвращать данные.

Способ 3. Использование вложенного запроса в параметрах среза

Еще один вариант — получение ссылки на вид цен с помощью подзапроса непосредственно в параметрах виртуальной таблицы:


ВЫБРАТЬ
	Цены.Номенклатура КАК Номенклатура,
	Цены.Цена КАК Цена
ИЗ
	РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
		&Период,
		ВидЦен В (
			ВЫБРАТЬ ПЕРВЫЕ 1
				Спр.Ссылка
			ИЗ
				Справочник.ВидыЦен КАК Спр
			ГДЕ
				Спр.Код = "000022"
		)
	) КАК Цены

Этот способ позволяет изолировать выборку ссылки внутри самого запроса, однако стандартная передача параметра Запрос.УстановитьПараметр() остается более прозрачной и предпочтительной для оптимизации СУБД.

Где и как хранится себестоимость номенклатуры в 1С

Рассмотрим частый сопутствующий вопрос: можно ли получить фактическую себестоимость номенклатуры из регистра сведений ЦеныНоменклатуры, не указывая вид цены?

  1. Платформенное устройство: сама технологическая платформа 1С не хранит понятие «себестоимость» автоматически — структура хранения зависит от конкретной конфигурации.
  2. Назначенные цены: в регистре сведений ЦеныНоменклатуры хранятся исключительно статические прайсовые или расчетные цены (включая вид цены с наименованием «Себестоимость», если он заведен вручную).
  3. Фактическая себестоимость: рассчитывается при проведении документов и хранится в регистрах накопления (например, СебестоимостьТоваров, ПартииТоваровНаСкладах, ВыручкаИСебестоимостьПродаж в конфигурациях ERP, КА, УТ или Запасы в УНФ) либо на счетах бухгалтерского учета (счета 41, 43 в регистре бухгалтерии Хозрасчетный в 1С:Бухгалтерии). Получать учетную себестоимость из регистра сведений цен методически некорректно.
← На главную