Срез последних в запросе 1С: СрезПоследних и СрезПервых

Дата: 06.10.2026 16:54:16
Запросы
Язык запросов
Регистры сведений
Виртуальные таблицы
Цены и курсы валют
УТ 11
Комментарий:
0
Платформа:
8.3
Конфигурация:
Любая
Формы:
Любые

Срез последних 1С — виртуальная таблица СрезПоследних периодического регистра сведений: по каждой комбинации измерений она возвращает самую позднюю запись не позже заданной даты. Так получают действующую цену, курс валюты на дату документа, любое значение «на момент». СрезПервых — её пара: самая ранняя запись не раньше даты. Ниже — параметры Период и Условие, готовые функции для цен и курсов и главная ошибка: почему условие в ГДЕ даёт неправильный срез. Имена регистров сверены по УТ 11.4 и КА 2.5, приём одинаков в любой конфигурации на платформе 8.3.

Где встречается задача

Срез нужен везде, где значение меняется со временем, а прочитать его надо на конкретный момент: цена на дату документа, прайс-лист в отчёте, выгрузка цен на сайт и маркетплейсы, пересчёт валюты по курсу.

  • Цены. В УТ 11.4 и КА 2.5 — регистр ЦеныНоменклатуры: измерения Номенклатура, Характеристика, ВидЦены, ресурсы Цена, Упаковка, Валюта. Периодичность — секунда, регистр подчинён регистратору: в УТ 11.4 документ «Установка цен номенклатуры» в статусе «Согласован» пишет записи с периодом, равным дате документа.
  • Курсы валют. Регистр КурсыВалют из БСП: измерение Валюта, ресурсы Курс и Кратность, периодичность — день.

Записи регистра видно через «Все функции» → «Регистры сведений» → «Цены номенклатуры». В КА 2.5 при «Ценообразовании 2.5» (константа ИспользуетсяЦенообразование25) цены могут лежать в регистре ЦеныНоменклатуры25 с другими измерениями — проверьте, какой регистр заполнен в вашей базе.

Как работает срез последних в 1С: параметры Период и Условие

Синтаксис: РегистрСведений.ИмяРегистра.СрезПоследних(Период, Условие). Оба параметра необязательные, пропущенный первый обозначают запятой: СрезПоследних(, ВидЦены = &ВидЦены). В конструкторе запроса их задают в окне «Параметры виртуальной таблицы». Основы языка — в статье о синтаксисе запросов.

ПараметрЧто передаватьЕсли не задан
ПериодДата, МоментВремени или Граница; дата берётся включительноСамые поздние записи без ограничения по дате, включая будущие
УсловиеУсловие по полям регистра: измерениям, ресурсам, реквизитам, Регистратор — без псевдонима таблицыСрез строится по всем записям

Главное из синтакс-помощника: условие применяется к исходным записям, а не к уже отобранным. Платформа сначала оставляет записи, подходящие под Период и Условие, потом по каждой комбинации измерений берёт самую позднюю. Незафиксированные измерения размножают строки: без отбора по ВидЦены срез вернёт строку на каждый вид цен товара. В 1С 8.3 срез последних берёт только активные записи, а в режиме совместимости 8.3.17 и ниже — и неактивные (у УТ 11.4.14 режим 8.3.18, у КА 2.5.20 — 8.3.24).

Пример — цены на дату по списку товаров в валюте цены и в рублях. Функция серверная: Запрос на тонком клиенте недоступен.

// Цены вида цен на дату: в валюте цены и в рублях по курсу на ту же дату.
// Серверный код: общий модуль, модуль менеджера или модуль объекта обработки.
// Регистры ЦеныНоменклатуры и КурсыВалют - УТ 11.4 и КА 2.5.
// СписокНоменклатуры - массив или список значений со ссылками на номенклатуру.
Функция ЦеныНаДату(ВидЦены, Дата, СписокНоменклатуры) Экспорт

	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ
	|	Цены.Номенклатура КАК Номенклатура,
	|	Цены.Характеристика КАК Характеристика,
	|	Цены.Упаковка КАК Упаковка,
	|	Цены.Цена КАК Цена,
	|	Цены.Валюта КАК Валюта,
	|	Цены.Период КАК ЦенаДействуетС,
	|	ВЫБОР
	|		КОГДА ЕСТЬNULL(Курсы.Кратность, 0) = 0
	|			ТОГДА 0
	|		ИНАЧЕ ВЫРАЗИТЬ(Цены.Цена * Курсы.Курс / Курсы.Кратность КАК ЧИСЛО(15, 2))
	|	КОНЕЦ КАК ЦенаВРублях
	|ИЗ
	|	РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
	|			&Дата,
	|			ВидЦены = &ВидЦены
	|				И Номенклатура В (&СписокНоменклатуры)) КАК Цены
	|		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют.СрезПоследних(&Дата) КАК Курсы
	|		ПО Цены.Валюта = Курсы.Валюта";

	// Цены в регистре заданы с точностью до секунды, курсы - по дням.
	// Для "цены на день" передайте КонецДня(Дата), для цены документа - его дату.
	Запрос.УстановитьПараметр("Дата", Дата);
	Запрос.УстановитьПараметр("ВидЦены", ВидЦены);
	Запрос.УстановитьПараметр("СписокНоменклатуры", СписокНоменклатуры);

	// Товара без цены этого вида в результате не будет: срез возвращает только
	// существующие записи. Нужен полный список - соединяйте срез с товарами.
	Возврат Запрос.Выполнить().Выгрузить();

КонецФункции

Разбор ключевых строк

  • СрезПоследних(&Дата, ВидЦены = &ВидЦены И Номенклатура В (&СписокНоменклатуры)) — дата и отборы в параметрах: срез строится только по нужным записям. Вместо списка подойдёт подзапрос к временной таблице, как в общем модуле Ценообразование УТ 11.4.
  • КурсыВалют.СрезПоследних(&Дата) — второй срез на ту же дату, без условия: валют в базе немного.
  • ЛЕВОЕ СОЕДИНЕНИЕ и ЕСТЬNULL(Курсы.Кратность, 0) = 0 — цена без курса не теряется и не вызывает деления на ноль, а получает 0 в колонке ЦенаВРублях.
  • Цены.Цена * Курсы.Курс / Курсы.Кратность — курс в БСП указан за Кратность единиц валюты. Для рубля есть запись 1/1: БСП добавляет её на 01.01.1980 при записи валюты. Цена в УТ 11.4 задана за Упаковку — для базовой единицы учитывайте коэффициент.

Почему условие в ГДЕ даёт неправильный срез

Виртуальная таблица вычисляется раньше, чем срабатывает ГДЕ. Условие в параметрах решает, из каких записей выбирать последнюю, условие в ГДЕ — какие из найденных последних записей оставить. Для измерений результат совпадает, для периода и ресурсов — нет. Пример: по розничному виду цен кофе стоит 500 с 01.03 и 550 с 20.03, чай — 300 с 05.03; нужны цены на 10.03.

ЗапросКофеЧай
СрезПоследних(&Дата, ВидЦены = &ВидЦены)500300
СрезПоследних без параметров + ГДЕ Цены.Период <= &Датастроки нет300

Во втором варианте срез взят без даты: последняя запись кофе — от 20.03, и ГДЕ её отбросил. Ошибки нет, товар молча пропадает. Пакет ниже показывает этот случай и условие на ресурс — выполните его в консоли запросов с параметрами Дата и ВидЦены.

// Пакет для консоли запросов. Параметры: Дата, ВидЦены.
// Запрос 1. НЕПРАВИЛЬНО: срез без даты (самые поздние записи вообще), дата - в ГДЕ.
// Товар, цену которого меняли после &Дата, пропадёт из результата.
ВЫБРАТЬ
	Цены.Номенклатура КАК Номенклатура,
	Цены.Характеристика КАК Характеристика,
	Цены.Цена КАК Цена
ИЗ
	РегистрСведений.ЦеныНоменклатуры.СрезПоследних КАК Цены
ГДЕ
	Цены.Период <= &Дата
	И Цены.ВидЦены = &ВидЦены
;

// Запрос 2. ПРАВИЛЬНО: дата и вид цен - в параметрах виртуальной таблицы.
ВЫБРАТЬ
	Цены.Номенклатура КАК Номенклатура,
	Цены.Характеристика КАК Характеристика,
	Цены.Цена КАК Цена
ИЗ
	РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Дата, ВидЦены = &ВидЦены) КАК Цены
;

// Запрос 3. Ресурс в ГДЕ: товары, у которых ПОСЛЕДНЯЯ цена больше нуля.
// Если цену обнулили, товара в выборке не будет.
ВЫБРАТЬ
	Цены.Номенклатура КАК Номенклатура,
	Цены.Характеристика КАК Характеристика,
	Цены.Цена КАК Цена
ИЗ
	РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Дата, ВидЦены = &ВидЦены) КАК Цены
ГДЕ
	Цены.Цена > 0
;

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

У ЦеныНоменклатуры и КурсыВалют в УТ 11.4 и КА 2.5 включено «Разрешить итоги: срез последних» — отдельная таблица последних значений для быстрого среза на текущий момент. По синтакс-помощнику она не используется, если в Условии есть поля кроме измерений и разделителей.

Срез последних на дату: время, граница и будущие записи

Чтобы получить срез последних на дату в запросе 1С, дату передают первым параметром. Нюансы такие.

  • Периодичность. У КурсыВалют она дневная, время не влияет. У ЦеныНоменклатуры — секунда: цену, установленную в 18:00, документ от 10:00 того же дня не увидит. Для «цены на день» передают конец дня — так в УТ 11.4 берутся цены поставщиков: КОНЕЦПЕРИОДА(&Дата, ДЕНЬ). Функции дат — в статье о дате в запросе 1С.
  • Срез без даты — не «на сегодня». Записи будущими датами, например заранее назначенные цены, он тоже вернёт. Для отчёта «на сегодня» передавайте ТекущаяДатаСеанса().
  • Граница. Новый Граница(Дата, ВидГраницы.Исключая) — срез строго до даты. Конструктор Граница на тонком клиенте недоступен, параметр собирают на сервере.

Пример с границей: какие цены изменились за день.

// Какие цены вида цен изменились за день: старая и новая цена.
// Срез на конец дня сравнивается со срезом строго до начала дня.
// Серверный код; регистр ЦеныНоменклатуры - УТ 11.4 и КА 2.5.
Функция ИзмененияЦенЗаДень(ВидЦены, ДатаДня) Экспорт

	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ
	|	Новые.Номенклатура КАК Номенклатура,
	|	Новые.Характеристика КАК Характеристика,
	|	ЕСТЬNULL(Старые.Цена, 0) КАК СтараяЦена,
	|	Новые.Цена КАК НоваяЦена,
	|	Новые.Период КАК ВремяИзменения
	|ИЗ
	|	РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&КонецДня, ВидЦены = &ВидЦены) КАК Новые
	|		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&ДоНачалаДня, ВидЦены = &ВидЦены) КАК Старые
	|		ПО Новые.Номенклатура = Старые.Номенклатура
	|			И Новые.Характеристика = Старые.Характеристика
	|ГДЕ
	|	Новые.Период >= &НачалоДня
	|	И (Старые.Цена ЕСТЬ NULL
	|			ИЛИ Старые.Цена <> Новые.Цена
	|			ИЛИ Старые.Упаковка <> Новые.Упаковка)
	|
	|УПОРЯДОЧИТЬ ПО
	|	ВремяИзменения";

	Запрос.УстановитьПараметр("ВидЦены", ВидЦены);
	Запрос.УстановитьПараметр("НачалоДня", НачалоДня(ДатаДня));
	Запрос.УстановитьПараметр("КонецДня", КонецДня(ДатаДня));
	// Исключая: записи ровно на начало дня в "старый" срез не попадут.
	// Конструктор Граница на тонком клиенте недоступен - только сервер.
	Запрос.УстановитьПараметр("ДоНачалаДня", Новый Граница(НачалоДня(ДатаДня), ВидГраницы.Исключая));

	Возврат Запрос.Выполнить().Выгрузить();

КонецФункции

Условие на Период здесь стоит в ГДЕ намеренно: нужен не срез на начало дня, а отбор готового среза — «последняя цена установлена сегодня».

СрезПервых: первая запись не раньше даты

СрезПервых(Период, Условие) устроен зеркально: по каждой комбинации измерений — самая ранняя запись с периодом не раньше даты (включительно), без даты — самая первая запись за всю историю. Типичных применений два: когда значение появилось впервые и какое изменение запланировано следующим.

// СрезПервых без даты: самая ранняя запись по каждому товару за всю историю.
// Новинки прайса - товары, которым ПЕРВУЮ цену вида назначили не раньше даты.
// Дата стоит в ГДЕ намеренно: СрезПервых(&НачалоПериода, ...) вернул бы
// и старые товары, у которых цена просто менялась после этой даты.
Функция НовинкиПрайса(ВидЦены, НачалоПериода) Экспорт

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

	Запрос.УстановитьПараметр("ВидЦены", ВидЦены);
	Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(НачалоПериода));

	Возврат Запрос.Выполнить().Выгрузить();

КонецФункции

// СрезПервых после даты: ближайшее запланированное изменение цены
// и цена, которая действует сейчас. Исключая - запись ровно на момент
// Дата уже действует и в "будущие" не попадает.
Функция ЗапланированныеЦены(ВидЦены, Дата) Экспорт

	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ
	|	Будущие.Номенклатура КАК Номенклатура,
	|	Будущие.Характеристика КАК Характеристика,
	|	ЕСТЬNULL(Текущие.Цена, 0) КАК ТекущаяЦена,
	|	Будущие.Цена КАК НоваяЦена,
	|	Будущие.Период КАК ДействуетС
	|ИЗ
	|	РегистрСведений.ЦеныНоменклатуры.СрезПервых(&ПослеДаты, ВидЦены = &ВидЦены) КАК Будущие
	|		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Дата, ВидЦены = &ВидЦены) КАК Текущие
	|		ПО Будущие.Номенклатура = Текущие.Номенклатура
	|			И Будущие.Характеристика = Текущие.Характеристика
	|
	|УПОРЯДОЧИТЬ ПО
	|	ДействуетС";

	Запрос.УстановитьПараметр("ВидЦены", ВидЦены);
	Запрос.УстановитьПараметр("Дата", Дата);
	Запрос.УстановитьПараметр("ПослеДаты", Новый Граница(Дата, ВидГраницы.Исключая));

	Возврат Запрос.Выполнить().Выгрузить();

КонецФункции

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

ПолучитьПоследнее и СрезПоследних в коде: методы менеджера регистра

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

// Модуль формы документа или обработки с реквизитами Валюта и Дата.
&НаКлиенте
Процедура ПоказатьКурс(Команда)

	ДанныеКурса = КурсНаДату(Объект.Валюта, Объект.Дата);
	Если ДанныеКурса.Курс = 0 Тогда
		ПоказатьПредупреждение(, "Курс валюты на дату не найден.");
	Иначе
		ПоказатьПредупреждение(, СтрШаблон("Курс: %1 руб. за %2 ед. валюты",
			ДанныеКурса.Курс, ДанныеКурса.Кратность));
	КонецЕсли;

КонецПроцедуры

// На тонком клиенте нет свойства РегистрыСведений: срез берём на сервере.
// Структура с числами без проблем возвращается на клиент.
&НаСервереБезКонтекста
Функция КурсНаДату(Валюта, Дата)

	// Дата не заполнена - берём текущую дату сеанса.
	ДатаСреза = ?(ЗначениеЗаполнено(Дата), Дата, ТекущаяДатаСеанса());

	// ПолучитьПоследнее возвращает структуру ресурсов Курс и Кратность.
	// Записи на дату нет - ресурсы пустые: Курс = 0, Кратность = 0.
	Отбор = Новый Структура("Валюта", Валюта);
	Возврат РегистрыСведений.КурсыВалют.ПолучитьПоследнее(ДатаСреза, Отбор);

КонецФункции

Нет записи на дату — ПолучитьПоследнее вернёт пустые ресурсы (Курс = 0), так проверяет результат и сама БСП. Курс 1 при кратности 1 у доллара — курсы до этой даты не загружались вовсе, и срез нашёл служебную запись от 01.01.1980. В БСП есть обёртка РаботаСКурсамиВалют.ПолучитьКурсВалюты(Валюта, ДатаКурса) — в УТ 11.4 и КА 2.5. Для списка валют или товаров методы в цикле не годятся: каждый вызов — отдельное обращение к базе.

Типичные ошибки

  • Дата в ГДЕ вместо параметра — пропадают товары с новой ценой после даты.
  • Срез без даты в отчёте «на дату» — в отчёт попадают будущие цены.
  • Дубли строк после соединения — зафиксированы не все измерения: без отбора по ВидЦены срез даёт строку на каждый вид цен.
  • «Поле не найдено …» — в Условии псевдоним таблицы (Цены.ВидЦены) или поле другой таблицы; доступны поля самого регистра, параметры и вложенные запросы.
  • «Не задано значение параметра "Дата"» — параметр не передан через УстановитьПараметр.
  • Цена не видна в день установки — срез на НачалоДня при периодичности «секунда».
  • «Переменная не определена (РегистрыСведений)» — метод менеджера вызван на клиенте; нужна функция &НаСервереБезКонтекста.
  • Срез у непериодического регистра — таких таблиц у него нет, используйте основную таблицу.

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

Чем СрезПоследних отличается от ВЫБРАТЬ ПЕРВЫЕ 1 с сортировкой по периоду?

ПЕРВЫЕ 1 с УПОРЯДОЧИТЬ ПО Период УБЫВ вернёт одну запись на весь запрос — это для одного товара. Срез даёт запись на каждую комбинацию измерений.

Как сделать срез последних в отчёте на СКД?

В наборе данных «Запрос» срез пишут так же, параметр &Дата СКД добавит в параметры отчёта сама. Если дата своя у каждой строки — см. статью о срезе последних в СКД.

Есть ли срез последних у регистра накопления?

Нет, срезы есть только у периодических регистров сведений. У регистра накопления значения на дату дают таблицы Остатки и ОстаткиИОбороты — см. статью об остатках в запросе.

Почему срез не видит цену из нового документа установки цен?

Причин обычно две. Время: период записи равен дате документа с точностью до секунды, и срез на более ранний момент её не видит. Статус: в УТ 11.4 «Установка цен номенклатуры» пишет цены в регистр только в статусе «Согласован».

Когда проще заказать

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

По теме

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

Станьте частью сообщества!
Войдите или зарегистрируйтесь, и вы сможете участвовать в обсуждениях.


1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.