Как преобразовать ежедневные записи регистра сведений в непрерывные временные периоды?

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

Зачастую перед разработчиком 1С встает задача: имеется регистр сведений, в котором ежедневно фиксируется состояние объекта (например, «действителен» или «недействителен»). Поставлена цель — сформировать отчет, который покажет не список дат, а конкретные промежутки времени, в течение которых состояние объекта оставалось неизменным. Эту задачу в профессиональной среде называют поиском «островков» (Gaps and Islands).

Разберем логику решения

Суть проблемы заключается в том, что нам нужно сгруппировать последовательные записи с одинаковым значением в единый интервал. Если объект имел статус «действителен» с 1 по 3 января, а 4 января сменил статус на «недействителен», нам нужно получить две записи: с 01.01 по 03.01 и с 04.01 и далее.

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

Реализация через запрос 1С

Рассмотрим пошаговый алгоритм, который поможет нам свести данные к нужному виду. Сначала мы должны определить для каждой записи дату следующего изменения состояния. Это делается путем левого соединения регистра самого с собой, где условием соединения является принадлежность одному объекту и дата больше текущей.

Проанализируем программный код, который решает эту задачу через вложенные группировки:


ВЫБРАТЬ 
    СостояниеРаботыУстройств.Устройство,
    СостояниеРаботыУстройств.Состояние,
    МИНИМУМ(СостояниеРаботыУстройств.НачПериод) КАК НачПериод,
    СостояниеРаботыУстройств.КонПериод КАК КонПериод
 ИЗ
(ВЫБРАТЬ
    СостояниеРаботыУстройств.Устройство КАК Устройство,
    СостояниеРаботыУстройств.Включено КАК Состояние,
    СостояниеРаботыУстройств.ДатаСостояния КАК НачПериод,
    МИНИМУМ(СостояниеРаботыУстройств1.ДатаСостояния) КАК КонПериод
ИЗ
    РегистрСведений.СостояниеРаботыУстройств КАК СостояниеРаботыУстройств
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СостояниеРаботыУстройств КАК СостояниеРаботыУстройств1
        ПО (СостояниеРаботыУстройств.Устройство = СостояниеРаботыУстройств1.Устройство)
            И (СостояниеРаботыУстройств.ДатаСостояния < СостояниеРаботыУстройств1.ДатаСостояния)
            И (СостояниеРаботыУстройств.Включено <> СостояниеРаботыУстройств1.Включено)
 СГРУППИРОВАТЬ ПО
    СостояниеРаботыУстройств.Устройство,
    СостояниеРаботыУстройств.ДатаСостояния,
    СостояниеРаботыУстройств.Включено) КАК СостояниеРаботыУстройств
СГРУППИРОВАТЬ ПО
    СостояниеРаботыУстройств.Устройство,
    СостояниеРаботыУстройств.Состояние,
    СостояниеРаботыУстройств.КонПериод

Разбор ключевых моментов запроса

  1. Внутренний запрос: Мы соединяем регистр сам с собой, используя условие СостояниеРаботыУстройств.Включено <> СостояниеРаботыУстройств1.Включено. Это критически важное условие, которое отсекает «шум» и оставляет только те строки, где действительно произошло изменение статуса.
  2. Группировка: Использование агрегатной функции МИНИМУМ(СостояниеРаботыУстройств1.ДатаСостояния) позволяет найти ближайшую точку во времени, когда состояние объекта изменилось на противоположное.
  3. Внешний запрос: Вторая группировка необходима для корректного схлопывания интервалов, чтобы на выходе получить чистые даты «С» и «ПО» для каждого статуса.

Важные советы по оптимизации и доработке

Работая с большими объемами данных, важно учитывать следующие моменты:

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

← На главную