Как получить первую запись регистра на определенную дату в СКД 1С?

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

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

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

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


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

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

Способ 2. Связи наборов данных в СКД (Передача параметров)

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

Разберем этот процесс по шагам:

  1. Создаем НаборДанных1 (запрос по документам): Напишем простой запрос, который выбирает список документов. Назовем это поле Ссылка.
  2. Создаем НаборДанных2 (запрос по регистру): Во втором наборе данных пишем запрос к виртуальной таблице регистра сведений, где в параметрах ограничиваем выборку по конкретному документу и статусу:

ВЫБРАТЬ
    Рег.Документ КАК Документ,
    Рег.Период КАК Период,
    Рег.Ответственный КАК Ответственный
ИЗ
    РегистрСведений.ИсторияСтатусов.СрезПервых(&Период, Документ = &ДокументПараметр И Статус = &СтатусПараметр) КАК Рег
  1. Настраиваем связи: Переходим на вкладку «Связи наборов данных». В качестве источника связи указываем НаборДанных1, приемником выбираем НаборДанных2. В колонке «Выражение источника» пишем Ссылка, а в колонке «Параметр» указываем наш созданный параметр ДокументПараметр. Если требуется ограничить срез датой документа, связываем поле Дата источника с параметром Период приемника.

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

Способ 3. Оптимальная эмуляция среза через временные таблицы

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

Давайте рассмотрим этот алгоритм подробнее:

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


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

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


ВЫБРАТЬ
    Док.Ссылка КАК Документ,
    ВТ_ПервыеДаты.МинимальныйПериод КАК ПериодПервойЗаписи,
    РегДанные.Ответственный КАК Ответственный
ИЗ
    Документ.НашДокумент КАК Док
    ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ПервыеДаты КАК ВТ_ПервыеДаты
        ПО Док.Ссылка = ВТ_ПервыеДаты.Документ
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ИсторияСтатусов КАК РегДанные
        ПО ВТ_ПервыеДаты.Документ = РегДанные.Документ
        И ВТ_ПервыеДаты.МинимальныйПериод = РегДанные.Период
        И РегДанные.Статус = &Статус

Такой подход работает чрезвычайно быстро, так как СУБД использует индексы по полям Документ и Период. Мы полностью избегаем использования ресурсоемких вложенных запросов с конструкцией ВЫБРАТЬ ПЕРВЫЕ 1 внутри соединений, которая часто вызывает проблемы с производительностью на SQL-серверах.

Важные нюансы и подводные камни

При работе с первой записью регистра обязательно учитывайте следующие технические особенности платформы 1С:

  1. Множественность измерений. Помните, что стандартная виртуальная таблица СрезПервых работает в разрезе ВСЕХ измерений регистра сведений. Если ваш регистр содержит дополнительные измерения (например, «Организация» или «Склад»), то СрезПервых вернет первую запись для каждого уникального сочетания этих измерений. Если вам нужна строго одна первая запись по документу в целом, используйте ручную эмуляцию через агрегатную функцию МИНИМУМ с группировкой исключительно по полю Документ.
  2. Флаг активности записей. В регистрах, подчиненных регистратору, существует системное поле Активность. Виртуальные таблицы платформы автоматически игнорируют неактивные записи (например, сторнированные движения). При написании ручной эмуляции (Способ 3) обязательно добавляйте условие ГДЕ Рег.Активность = ИСТИНА, чтобы ваши данные полностью соответствовали логике платформы.

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

← На главную