Зачастую перед разработчиком 1С встает задача: имеется регистр сведений, в котором ежедневно фиксируется состояние объекта (например, «действителен» или «недействителен»). Поставлена цель — сформировать отчет, который покажет не список дат, а конкретные промежутки времени, в течение которых состояние объекта оставалось неизменным. Эту задачу в профессиональной среде называют поиском «островков» (Gaps and Islands).
Суть проблемы заключается в том, что нам нужно сгруппировать последовательные записи с одинаковым значением в единый интервал. Если объект имел статус «действителен» с 1 по 3 января, а 4 января сменил статус на «недействителен», нам нужно получить две записи: с 01.01 по 03.01 и с 04.01 и далее.
Для решения этой задачи мы воспользуемся механизмом самосоединения таблицы регистра. Мы будем сравнивать каждую запись с последующими, чтобы найти момент изменения статуса.
Рассмотрим пошаговый алгоритм, который поможет нам свести данные к нужному виду. Сначала мы должны определить для каждой записи дату следующего изменения состояния. Это делается путем левого соединения регистра самого с собой, где условием соединения является принадлежность одному объекту и дата больше текущей.
Проанализируем программный код, который решает эту задачу через вложенные группировки:
ВЫБРАТЬ
СостояниеРаботыУстройств.Устройство,
СостояниеРаботыУстройств.Состояние,
МИНИМУМ(СостояниеРаботыУстройств.НачПериод) КАК НачПериод,
СостояниеРаботыУстройств.КонПериод КАК КонПериод
ИЗ
(ВЫБРАТЬ
СостояниеРаботыУстройств.Устройство КАК Устройство,
СостояниеРаботыУстройств.Включено КАК Состояние,
СостояниеРаботыУстройств.ДатаСостояния КАК НачПериод,
МИНИМУМ(СостояниеРаботыУстройств1.ДатаСостояния) КАК КонПериод
ИЗ
РегистрСведений.СостояниеРаботыУстройств КАК СостояниеРаботыУстройств
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СостояниеРаботыУстройств КАК СостояниеРаботыУстройств1
ПО (СостояниеРаботыУстройств.Устройство = СостояниеРаботыУстройств1.Устройство)
И (СостояниеРаботыУстройств.ДатаСостояния < СостояниеРаботыУстройств1.ДатаСостояния)
И (СостояниеРаботыУстройств.Включено <> СостояниеРаботыУстройств1.Включено)
СГРУППИРОВАТЬ ПО
СостояниеРаботыУстройств.Устройство,
СостояниеРаботыУстройств.ДатаСостояния,
СостояниеРаботыУстройств.Включено) КАК СостояниеРаботыУстройств
СГРУППИРОВАТЬ ПО
СостояниеРаботыУстройств.Устройство,
СостояниеРаботыУстройств.Состояние,
СостояниеРаботыУстройств.КонПериод
СостояниеРаботыУстройств.Включено <> СостояниеРаботыУстройств1.Включено. Это критически важное условие, которое отсекает «шум» и оставляет только те строки, где действительно произошло изменение статуса.МИНИМУМ(СостояниеРаботыУстройств1.ДатаСостояния) позволяет найти ближайшую точку во времени, когда состояние объекта изменилось на противоположное.Работая с большими объемами данных, важно учитывать следующие моменты:
ЕСТЬNULL(КонПериод, ТекущаяДата()).Дата1 < Дата2) на регистрах с миллионами записей. В таких случаях лучше сначала отобрать изменения статусов во временную таблицу, и только потом производить расчет интервалов.Применяя этот подход, вы сможете эффективно трансформировать любые периодические данные в понятные временные интервалы, что значительно повысит информативность ваших отчетов для пользователей и руководства.