Как выбрать первую запись периодического регистра сведений для каждого измерения в 1С?

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

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

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

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

Самым очевидным и простым способом получения первых записей является использование виртуальной таблицы СрезПервых. Эта таблица специально предназначена для получения наиболее ранних записей на определенный момент времени.

Проанализируем особенности этого метода. Если нам нужно получить самые первые записи за всю историю ведения учета, мы можем вызвать виртуальную таблицу без указания параметра Период или передать в него пустую дату (01.01.0001).

Рассмотрим пример запроса:


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

Преимущества метода:

  1. Простота написания: Платформа берет на себя всю логику по поиску минимальных дат.
  2. Корректная обработка измерений: Запрос автоматически вернет записи по каждой уникальной комбинации измерений регистра.
  3. Получение всех полей: Мы сразу получаем не только дату и измерения, но и ресурсы, а также реквизиты записи.

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

Метод 2. Группировка по физической таблице (Минимум по периоду)

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

Суть метода заключается в использовании агрегатной функции МИНИМУМ(Период) с группировкой по всем необходимым измерениям. Посмотрим на пример:


ВЫБРАТЬ
    КурсыВалют.Валюта КАК Валюта,
    МИНИМУМ(КурсыВалют.Период) КАК Период
ИЗ
    РегистрСведений.КурсыВалют КАК КурсыВалют
ГРУППИРОВАТЬ ПО
    КурсыВалют.Валюта

Этот запрос эффективно использует индекс по периоду и измерениям, который 1С автоматически создает для периодических регистров. Но у этого метода есть существенное ограничение: мы не можем просто так добавить в этот запрос ресурсы (например, сам Курс), так как они не входят в группировку.

Метод 3. Получение ресурсов через временную таблицу и соединение

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

Разберем алгоритм по шагам:

  1. Создаем временную таблицу, в которую помещаем пары «Измерение — Минимальный Период».
  2. Соединяем полученную временную таблицу с основной физической таблицей регистра по соответствующим полям.
  3. Выбираем из физической таблицы все необходимые нам данные.

Посмотрим на пример реализации такого запроса:


// Шаг 1: Получаем минимальные даты во временную таблицу
ВЫБРАТЬ
    КурсыВалют.Валюта КАК Валюта,
    МИНИМУМ(КурсыВалют.Период) КАК Период
ПОМЕСТИТЬ ВТ_ПервыеДаты
ИЗ
    РегистрСведений.КурсыВалют КАК КурсыВалют
ГРУППИРОВАТЬ ПО
    КурсыВалют.Валюта
;

// Шаг 2: Соединяем с основной таблицей для получения ресурсов
ВЫБРАТЬ
    ВТ_ПервыеДаты.Валюта,
    ВТ_ПервыеДаты.Период КАК ДатаПервойКотировки,
    КурсыВалют.Курс КАК Курс
ИЗ
    ВТ_ПервыеДаты КАК ВТ_ПервыеДаты
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют КАК КурсыВалют
        ПО ВТ_ПервыеДаты.Валюта = КурсыВалют.Валюта
        И ВТ_ПервыеДаты.Период = КурсыВалют.Период

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

Метод 4. Проблема «одинаковых периодов» и использование кортежей

Проанализируем ситуацию, когда для одного измерения в одну и ту же секунду были введены две записи. Метод с МИНИМУМ(Период) вернет одну дату, но при соединении с основной таблицей по этой дате вы получите две строки вместо одной.

Чтобы гарантированно выбрать строго одну «самую первую» запись, профессионалы рекомендуют использовать дополнительные критерии сортировки:

Также для краткости кода можно использовать оператор В (ВЫБРАТЬ...) с кортежем полей в условии ГДЕ. Это позволяет избежать явного создания временных таблиц в тексте запроса:


ВЫБРАТЬ
    Рег.Валюта,
    Рег.Период,
    Рег.Курс
ИЗ
    РегистрСведений.КурсыВалют КАК Рег
ГДЕ
    (Рег.Валюта, Рег.Период) В 
        (ВЫБРАТЬ 
            Т.Валюта, 
            МИНИМУМ(Т.Период) 
         ИЗ 
            РегистрСведений.КурсыВалют КАК Т 
         ГРУППИРОВАТЬ ПО Т.Валюта)

Оптимизация производительности

Выясним, от чего зависит скорость выполнения таких запросов. В периодических регистрах 1С автоматически создает индекс Период + Измерения. Если ваш запрос строится по физической таблице через МИНИМУМ(Период), СУБД эффективно использует этот индекс.

Если вы планируете часто делать выборки «первой записи» по определенному измерению (например, по валюте), убедитесь, что это измерение стоит первым в списке измерений регистра в конфигураторе. Порядок измерений напрямую влияет на эффективность использования индексов в SQL.

Резюмируем:

  1. Для простых задач, где не критична скорость на миллионах строк, используйте СрезПервых.
  2. Если нужны только измерения и дата — используйте МИНИМУМ(Период) с группировкой.
  3. Если нужны ресурсы и высокая производительность — используйте временную таблицу с последующим соединением.
  4. Всегда помните о возможности совпадения периодов и при необходимости добавляйте в условия соединения поле Регистратор или НомерЗаписи.
← На главную