Как свернуть (схлопнуть) таблицу с временными интервалами в запросе 1С?

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

При работе с регистрами сведений часто возникает задача объединения данных. Например, необходимо вывести информацию о состоянии физического лица за определенные периоды, где одинаковые состояния, идущие подряд, должны отображаться как один непрерывный интервал с датой начала и датой окончания. Простая СГРУППИРОВАТЬ здесь не поможет, так как она не учитывает хронологическую последовательность записей. Давайте разберем, как решить эту задачу с помощью механизмов языка запросов 1С.

Метод 1: Использование АВТОНОМЕРЗАПИСИ для поиска соседних записей

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

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

  1. Сначала сформируем временную таблицу с исходными данными, добавив к ним АВТОНОМЕРЗАПИСИ.
  2. Выполним левое соединение этой таблицы с самой собой по условию равенства физического лица и смещения номера на единицу.

ВЫБРАТЬ 
    Рег.ФизическоеЛицо КАК ФизическоеЛицо, 
    Рег.Состояние КАК Состояние, 
    Рег.Период КАК Период, 
    АВТОНОМЕРЗАПИСИ() КАК Номер 
ПОМЕСТИТЬ Таб 
ИЗ РегистрСведений.СостоянияФизическихЛиц КАК Рег 
УПОРЯДОЧИТЬ ПО Рег.ФизическоеЛицо, Рег.Период; 

ВЫБРАТЬ 
    Рег1.ФизическоеЛицо,
    Рег1.Состояние,
    Рег1.Период КАК Начало, 
    Рег2.Период КАК Окончание 
ИЗ Таб КАК Рег1 
ЛЕВОЕ СОЕДИНЕНИЕ Таб КАК Рег2 
ПО Рег1.ФизическоеЛицо = Рег2.ФизическоеЛицо 
    И Рег1.Номер = Рег2.Номер - 1
УПОРЯДОЧИТЬ ПО Рег1.ФизическоеЛицо, Начало;

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

Метод 2: Итеративный подход (Метод замыканий)

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

Суть подхода заключается в использовании нескольких временных таблиц:

  1. Создаем исходный набор данных.
  2. Выполняем итеративное соединение, расширяя диапазоны (сначала на 2 шага, потом на 4, на 8 и так далее, используя логику двоичного поиска/увеличения длины связей).
  3. В финальной части запроса выполняем группировку для получения минимальной даты начала и максимальной даты окончания для каждого непрерывного отрезка.

// Пример логики итеративного сбора данных
ВЫБРАТЬ РАЗЛИЧНЫЕ 
    ПерваяДуга.НачалоДуги, 
    ВтораяДуга.КонецДуги, 
    ВтораяДуга.Ссылка 
ПОМЕСТИТЬ Замыкания 
ИЗ ЗамыканияДлины1 КАК ПерваяДуга 
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ЗамыканияДлины1 КАК ВтораяДуга 
ПО ПерваяДуга.КонецДуги = ВтораяДуга.НачалоДуги;

Рекомендации по оптимизации

При работе с такими сложными запросами важно учитывать производительность:

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

← На главную