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

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

Срез последних в 1С: как работает и когда использовать

Как работает срез последних в 1С: синтаксис запроса, параметры периода и условия, производительность, типичные ошибки и выбор между срезом последних и первых.

Срез последних — виртуальная таблица периодического регистра сведений в 1С, которая возвращает по каждому набору измерений самую свежую запись на указанную дату. Классический пример: цены товаров, курсы валют, ФИО физического лица, ответственные лица организации — данные, которые меняются во времени, но актуально обычно только последнее значение.

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

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

Как платформа формирует срез последних

Периодический регистратор сведений хранит все значения с датами: например, цена товара на 10 января, 15 февраля, 3 марта. Когда вы обращаетесь к виртуальной таблице РегистрСведений.ЦеныТоваров.СрезПоследних, платформа для каждой уникальной комбинации измерений (например, для каждого товара) ищет запись с максимальным периодом, который меньше или равен переданной дате.

Если дата не указана, срез строится на текущий момент — фактически берутся самые последние записи в регистре без ограничения сверху. Это частый источник ошибок: разработчик ожидает данные на конкретную дату отчёта, а получает значения «на сегодня», включая записи из будущего периода.

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

Синтаксис запроса со срезом последних

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

ВЫБРАТЬ

СрезЦен.Номенклатура,

СрезЦен.Цена

ИЗ

РегистрСведений.ЦеныТоваров.СрезПоследних(&Период, ТипЦен = &ТипЦен) КАК СрезЦен

Дату удобно передавать через параметр запроса, предварительно установив его программно. В качестве периода допустимо передать и границу (объект Граница), когда нужно включить или исключить записи на точный момент времени — например, «на начало документа, не включая его самого».

Обратите внимание: условие в параметрах виртуальной таблицы применяется до вычисления среза. Это значит, что отбор ТипЦен = &ТипЦен ограничит набор записей, среди которых ищется последняя. Условие же в секции ГДЕ применяется уже к готовому результату среза — и это принципиально другая логика.

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

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

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

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

Отдельный случай — отбор по списку значений. В параметр условия можно передать таблицу значений или массив через конструкцию Номенклатура В (&СписокНоменклатуры). Это резко сокращает объём обрабатываемых записей и является основным приёмом оптимизации, когда срез нужен не по всему справочнику, а по сотне конкретных позиций.

Производительность: где срез теряет скорость

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

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

Отдельная ситуация — соединение основной таблицы со срезом. Если соединяется, например, таблица товаров документа со срезом цен, сначала поместите товары во временную таблицу, а затем соединяйтесь со срезом с условием по этой таблице через вложенный запрос или отбор в параметрах. Так СУБД вычислит срез только по нужным позициям.

Как ускорить запрос со срезом
  1. 1
    Сформируйте список нужных значений измерений (номенклатуры, валюты) и передайте его в условие виртуальной таблицы через В (&Параметр)
  2. 2
    Укажите период среза явно — не оставляйте параметр пустым без необходимости
  3. 3
    Уберите соединение со срезом из цикла: соберите ключи заранее и выполните один запрос
  4. 4
    Проверьте время выполнения на копии базы с реальным объёмом данных и при необходимости посмотрите план запроса

Срез последних и срез первых: как выбрать

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

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

Срез последних и срез первых

Срез последних

Ищет максимальный период, не превышающий заданную дату. Подходит для актуальных на дату значений: цен, курсов, ответственных

Срез первых

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

Физическая таблица регистра

Нужна, когда требуется история изменений за интервал, а не одно значение на дату

Типичные ошибки при работе со срезом

Ошибки со срезом последних повторяются от проекта к проекту и обычно приводят либо к неправильным данным, либо к медленным запросам. Знание этих паттернов экономит часы отладки.

Типичные ошибки
01
Не задан период среза — в отчёт за прошлый месяц попадают значения, записанные позже, включая сегодняшние
02
Условие по измерению или ресурсу помещено в ГДЕ вместо параметров виртуальной таблицы — срез строится по всей таблице и логика отбора нарушается
03
Запрос со срезом выполняется в цикле по каждой строке документа вместо одного запроса по списку ключей
04
Используется срез последних там, где нужна история изменений за период — результат содержит только одну запись на ключ
05
Ожидается запись на дату, которой в регистре нет: срез вернёт более раннее значение, и это норма, а не ошибка — но об этом забывают при проверке

Отдельно стоит помнить о поведении при отсутствии записей: если по комбинации измерений до указанной даты записей нет вообще, такая комбинация просто не попадёт в результат среза. При соединении с основной таблицей используйте левое соединение и обрабатывайте значения NULL — например, подставляйте цену по умолчанию или выводите признак «цена не задана».

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

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

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

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

Как проверить корректность среза

Период среза
Норма

Передана явная дата отчёта или документа

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

Параметр пуст или содержит текущую дату сеанса

Расположение отборов
Норма

Условия по измерениям в параметрах виртуальной таблицы

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

Отборы только в секции ГДЕ

Граничная дата
Норма

Запись с периодом, равным дате среза, попадает в результат

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

Запись на саму дату теряется

Отсутствие записей
Норма

Ключи без записей обработаны через левое соединение и NULL

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

Строки молча пропадают из отчёта

FAQ: частые вопросы о срезе последних

Итог

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

Срез последних возвращает по каждой комбинации измерений самую позднюю запись не позже заданной даты. Всегда передавайте период и отборы в параметры виртуальной таблицы, избегайте запросов в цикле и помните: условие в ГДЕ фильтрует уже готовый срез, а не исходные записи.

Что вернёт срез последних, если не указать период?

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

Можно ли получить срез последних на момент документа?

Да. Передайте в параметр периода дату документа или объект Граница с моментом времени документа. Граница с видом «Исключая» позволит получить значения до проведения документа, что важно, например, при расчёте себестоимости без учёта собственных движений.

Почему запрос со срезом работает медленно и что делать в первую очередь?

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

Чем срез последних отличается от среза первых?

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

Почему в результате среза нет части товаров?

Если по комбинации измерений нет ни одной записи с периодом не позже даты среза, такая комбинация не попадает в виртуальную таблицу. При соединении с основной выборкой используйте левое соединение и обрабатывайте NULL в полях ресурсов.

Работает ли срез последних для регистров, подчинённых регистратору?

Да, виртуальная таблица доступна и для таких регистров. Дополнительно в результате присутствует поле регистратора, а при равном периоде нескольких записей учитывается момент времени документа-регистратора, что влияет на выбор «последней» записи.