Разработка и Конфигурация · 11 мин
Срез первых и срез последних в 1С: в чём разница
Разбираем разницу между виртуальными таблицами СрезПервых и СрезПоследних в 1С: синтаксис, параметры, примеры запросов, типичные ошибки и советы по производительности.
Виртуальные таблицы «СрезПервых» и «СрезПоследних» — стандартный инструмент языка запросов 1С для работы с регистрами сведений, у которых установлена периодичность (в пределах секунды, дня, месяца и т.д.). Обе таблицы возвращают записи регистра, актуальные на заданный момент времени, но делают это с противоположных сторон шкалы времени. СрезПоследних берёт самые свежие значения на дату, СрезПервых — самые ранние после указанной даты.
Типовой пример: регистр сведений «ЦеныНоменклатуры» хранит историю изменения цен. Чтобы узнать, какая цена действовала на дату документа, используют СрезПоследних. Чтобы узнать, когда цена изменится в будущем или какая цена была установлена первой после начала периода, применяют СрезПервых. Путаница между ними — одна из частых причин неверных цифр в отчётах.
Ниже разберём логику работы обеих таблиц, параметры, примеры запросов, ограничения по производительности и типичные ошибки, которые приводят к пустым или неверным результатам.
Как устроены виртуальные таблицы срезов
Обе таблицы существуют только для периодических регистров сведений. Если у регистра периодичность не установлена (независимый непериодический регистр), виртуальные таблицы СрезПервых и СрезПоследних недоступны — конструктор запросов их просто не покажет.
Логика работы определяется направлением поиска от точки отсчёта (параметра «Период»):
- СрезПоследних(&Период) ищет назад по времени: для каждой комбинации измерений берётся запись с максимальным периодом, меньшим или равным указанной дате.
- СрезПервых(&Период) ищет вперёд по времени: для каждой комбинации измерений берётся запись с минимальным периодом, большим или равным указанной дате.
Ключевое слово — «для каждой комбинации измерений». Срез не возвращает одну запись на весь регистр: он возвращает по одной записи на каждый уникальный набор измерений. Например, в регистре «КурсыВалют» с измерением «Валюта» срез вернёт по одной строке на каждую валюту, а не одну строку суммарно.
Срез последних: синтаксис и примеры
СрезПоследних — самая востребованная виртуальная таблица в учётных задачах. Она отвечает на вопрос «какое значение действует на дату». Пример запроса к регистру сведений «ЦеныНоменклатуры»:
ВЫБРАТЬ
Срез.Номенклатура,
Срез.Цена
ИЗ
РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ) КАК Срез
Второй параметр после периода — условие отбора. В нём можно ограничить измерения, например выбрать цены только по одному виду цен:
РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ВидЦены = &ВидЦены)
Если параметр «Период» не передать, платформа возьмёт срез на самую позднюю дату, присутствующую в регистре. Это удобно для получения текущих значений, но в отчётах за прошлый период приведёт к ошибке: будут показаны актуальные данные вместо исторических.
Срез первых: синтаксис и примеры
СрезПервых отвечает на вопрос «какое значение вступило в силу первым после даты». Типовые сценарии: определить первую цену нового периода, узнать дату первого изменения статуса, найти ближайшее будущее событие по графику.
ВЫБРАТЬ
Срез.Период,
Срез.Номенклатура,
Срез.Цена
ИЗ
РегистрСведений.ЦеныНоменклатуры.СрезПервых(&НачалоПериода, ) КАК Срез
Если в регистре на дату &НачалоПериода и позже по какой-то номенклатуре нет ни одной записи, эта позиция в результат не попадёт. Это симметрично поведению СрезПоследних: если до указанной даты записей не было, позиция тоже отсутствует в выборке.
На практике СрезПервых встречается заметно реже. Частая ситуация — анализ изменений: соединив СрезПоследних на конец периода со СрезПервых на начало, можно сравнить значения «было/стало» без чтения всей истории регистра.
Сравнение вариантов
Нужны действующие значения на дату: цены, курсы валют, ответственные лица, статусы. Ищет назад по времени от указанной даты.
Нужно первое значение, установленное после даты: стартовая цена периода, ближайшее будущее событие. Ищет вперёд по времени.
Нужны все записи за интервал, а не одна на измерение. Дешевле по ресурсам, но требует самостоятельной группировки.
Параметры и условия отбора: что важно учесть
У обеих таблиц два параметра: период и условие. Условие записывается не через ГДЕ, а прямо в скобках виртуальной таблицы — это принципиально важно для производительности. Отбор внутри параметра применяется до построения среза, а отбор в секции ГДЕ — после, то есть платформа сначала построит срез по всем измерениям, а потом отбросит лишнее.
Ограничения условия в параметрах виртуальной таблицы:
- можно отбирать только по измерениям регистра, ресурсы и реквизиты в условии недоступны;
- поддерживаются сравнения, В, В ИЕРАРХИИ, ПОДОБНО;
- нельзя использовать соединения с другими таблицами внутри условия — только параметры запроса.
Ещё один нюанс — граница включения даты. Оба среза включают запись, чей период точно равен переданной дате. Если передать дату без времени (начало дня), запись, сделанная в середине этого дня, в СрезПоследних не попадёт. Для отчётов «на конец дня» передавайте конец дня: КонецПериода(&Дата, День) или соответствующее значение, сформированное в коде.
Соединение среза с другими таблицами
Классическая задача — подтянуть действующую цену или курс к таблице документов, у каждого из которых своя дата. Здесь СрезПоследних с одним фиксированным параметром не подходит: дата у каждой строки своя. Правильный приём — соединение по условию «период регистра меньше или равен дате документа» с группировкой по максимуму периода, либо использование среза на фиксированную дату, если все документы в одном периоде.
Пример с фиксированной датой:
ВЫБРАТЬ
Товары.Номенклатура,
Цены.Цена
ИЗ
Документ.Реализация.Товары КАК Товары
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&ДатаДокумента, ) КАК Цены
ПО Товары.Номенклатура = Цены.Номенклатура
Используйте ЛЕВОЕ соединение: если по какой-то позиции записей в регистре нет, строка документа не потеряется, а поле цены будет NULL. Внутреннее соединение молча исключит такие строки, и итоги отчёта разойдутся с документом — это одна из самых коварных ошибок, потому что она не вызывает сообщений об ошибке.
- 1Определите, какой вопрос решаете: действующее значение на дату (СрезПоследних) или первое значение после даты (СрезПервых)
- 2Передайте период параметром и проверьте, что это корректная граница (конец дня для отчётов на дату)
- 3Условия по измерениям укажите в параметрах виртуальной таблицы, а не в секции ГДЕ
- 4Используйте ЛЕВОЕ СОЕДИНЕНИЕ и обработайте возможные NULL в ресурсах
- 5Проверьте результат на позиции, у которой записей в регистре нет, и на позиции с записью ровно на границе периода
Производительность и ограничения
Построение среза — относительно дорогая операция: платформе нужно сгруппировать записи по измерениям и найти экстремум периода в каждой группе. На регистрах с миллионами записей неосторожный запрос может выполняться заметное время, особенно если срез строится в цикле или внутри пакета запросов многократно.
Практические рекомендации:
- всегда ограничивайте состав измерений условием в параметрах — срез по одному виду цен строится существенно быстрее, чем по всем;
- не используйте срез, если нужны все записи за период, — обращайтесь к основной таблице регистра;
- при многократном использовании одного и того же среза в пакетном запросе поместите его во временную таблицу и сделайте на неё индекс по полям соединения;
- избегайте срезов внутри подзапросов с соединениями без предварительной фильтрации.
Типичные ошибки и как их избежать
Большинство проблем со срезами связано не с синтаксисом, а с логикой: запрос выполняется без ошибок, но возвращает не те данные. Ниже — ситуации, которые стоит проверять в первую очередь.
Отдельно отметим ситуацию с «размножением» строк. Если соединить таблицу документов со срезом, у которого измерений больше, чем указано в условии соединения (например, соединили только по номенклатуре, а в регистре есть ещё измерение «Организация»), каждая строка документа продублируется по числу организаций. Всегда соединяйте по полному набору измерений, участвующих в задаче.
Как проверить результат
Совпадает с числом строк исходной таблицы (при левом соединении)
Строк стало больше — срез содержит лишние измерения
Запись с периодом, равным дате, учтена
Запись на дату пропала — передано начало дня вместо конца
Строка присутствует, ресурс равен NULL
Строка отсутствует — использовано внутреннее соединение
FAQ
Что вернёт СрезПоследних, если не указать параметр периода?
Платформа построит срез на максимальную дату, присутствующую в регистре, то есть фактически самые свежие значения. Для отчётов за прошлый период это опасно: данные будут актуальными, а не историческими, поэтому параметр лучше передавать всегда явно.
Можно ли использовать срезы для регистров накопления?
Нет. СрезПервых и СрезПоследних существуют только у периодических регистров сведений. У регистров накопления свои виртуальные таблицы: Остатки, Обороты, ОстаткиИОбороты — они решают другие задачи.
Как получить последнее значение одного элемента без запроса?
Используйте метод менеджера регистра сведений: РегистрыСведений.ЦеныНоменклатуры.ПолучитьПоследнее(Дата, Отбор), где Отбор — структура с измерениями. Для одиночного чтения это проще и быстрее, чем конструировать запрос. Аналогично работает ПолучитьПервое().
Почему срез возвращает несколько строк, хотя я жду одну?
Срез строится по каждой уникальной комбинации измерений. Чтобы получить одну строку, передайте в условии виртуальной таблицы значения всех измерений регистра — тогда в срез попадёт только нужная комбинация.
Включает ли срез запись, сделанную ровно на указанную дату?
Да, обе таблицы включают записи, период которых равен переданному параметру. Но если дата передана без времени, она трактуется как начало дня, и записи, сделанные позже в течение этого дня, в СрезПоследних не попадут.
Что быстрее: срез или запрос к таблице регистра с группировкой по максимуму периода?
Ручная группировка по максимуму периода с последующим соединением иногда работает быстрее на очень больших регистрах, потому что позволяет точнее управлять планом запроса. Однако для большинства задач встроенный срез с корректными параметрами отбора достаточно эффективен и заметно проще в сопровождении.
Что важно запомнить
СрезПоследних ищет назад по времени и отвечает «что действует на дату», СрезПервых ищет вперёд и отвечает «что вступило в силу первым после даты». Обе таблицы работают только с периодическими регистрами сведений, возвращают по записи на каждую комбинацию измерений и требуют отбора по измерениям именно в параметрах — это главное условие корректного и быстрого запроса.