Как выбирать записи из регистра сведений на текущую дату

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

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

Использование виртуальной таблицы СрезПоследних

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

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


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

Важно понимать, что если параметр &Период не указан, 1С берет данные на «максимально возможную» дату в будущем. Однако в реальных задачах хорошим тоном считается явная передача параметра текущей даты сеанса.

Параметры виртуальной таблицы против секции ГДЕ

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

Вариант 1: Условие в параметрах виртуальной таблицы. Это наиболее правильный и производительный способ. Когда мы указываем отбор (например, по конкретной номенклатуре) непосредственно в скобках после СрезПоследних, система сначала ограничивает набор данных, а затем выполняет поиск последней записи только для этих объектов.


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

Вариант 2: Условие в секции ГДЕ. В этом случае система сначала построит срез последних по ВСЕМУ регистру, а затем из полученного результата отфильтрует нужную номенклатуру. На больших объемах данных это приведет к серьезным задержкам.


// ТАК ДЕЛАТЬ НЕ РЕКОМЕНДУЕТСЯ ПРИ БОЛЬШОМ ОБЪЕМЕ ДАННЫХ
ВЫБРАТЬ
    Срез.Цена
ИЗ
    РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период) КАК Срез
ГДЕ
    Срез.Номенклатура = &Номенклатура

Особенности фильтрации по ресурсам

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

Допустим, последняя цена товара — 150 рублей, а предыдущая (вчерашняя) — 90 рублей. Если вы напишете СрезПоследних(, Цена < 100), система отбросит запись со 150 рублями еще на этапе формирования среза и вернет вам вчерашнюю цену 90 рублей. Но ведь актуальная цена сейчас 150! Значит, условие «текущая цена < 100» не выполняется, и результат должен быть пустым.

Правило:

  1. Условия по измерениям (Номенклатура, Склад, Организация) всегда пишем в параметрах виртуальной таблицы.
  2. Условия по ресурсам (Цена, Сумма, Статус), если нам нужно проверить именно текущее состояние, пишем в секции ГДЕ.

Производительность и итоги среза последних

Посмотрим на ситуацию с точки зрения работы базы данных (SQL). Платформа 1С позволяет оптимизировать работу со срезом последних. В конфигураторе у периодических регистров сведений есть свойство «Использовать итоги для среза последних».

Если этот флаг включен:

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


ВЫБРАТЬ ПЕРВЫЕ 1
    Цены.Период,
    Цены.Цена
ИЗ
    РегистрСведений.ЦеныНоменклатуры КАК Цены
ГДЕ
    Цены.Номенклатура = &Номенклатура
УПОРЯДОЧИТЬ ПО
    Период УБЫВ

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

Граница периода и время

Разберем важный технический момент, связанный со временем. В 1С дата включает в себя время. Если вы передаете в запрос дату без времени (например, '2023-10-27 00:00:00'), то записи, сделанные в течение этого дня (например, в 12:00:00), в срез не попадут.

Для корректного получения данных на «сейчас» используйте один из двух подходов:

  1. Передавайте пустую дату (или не указывайте параметр вовсе).
  2. Используйте ТекущаяДатаСеанса() в качестве параметра.

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

Программный способ получения данных

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


Отбор = Новый Структура("Номенклатура", ВыбраннаяНоменклатура);
АктуальныеДанные = РегистрыСведений.ЦеныНоменклатуры.СрезПоследних(ТекущаяДатаСеанса(), Отбор);

Если АктуальныеДанные.Количество() > 0 Тогда
    ТекущаяЦена = АктуальныеДанные[0].Цена;
КонецЕсли;

Этот метод возвращает таблицу значений с одной строкой (если запись найдена). Это быстрее в написании и проще для чтения кода, если не требуется соединение с другими таблицами базы данных.

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

← На главную