При работе с временными отрезками в 1С часто возникает необходимость привести таблицу интервалов к непрерывному виду: объединить пересекающиеся периоды с одинаковым статусом, устранить пропуски и корректно обработать открытые даты завершения. Рассмотрим подробнее, как устроена эта логика и какими способами можно решить эту задачу.
Проанализируем ситуацию на примере исходной таблицы, в которой содержатся даты начала, даты завершения и булево состояние (ИСТИНА / ЛОЖЬ, или «Да» / «Нет»):
ИСТИНА), он поглощается более широким интервалом.ЛОЖЬ («Нет»).01.01.0001) означает, что состояние действует до момента следующего изменения статуса.Для отладки алгоритмов создадим временную таблицу ВТ прямо в консоли запросов 1С с помощью конструкции ОБЪЕДИНИТЬ ВСЕ:
ВЫБРАТЬ
ДАТАВРЕМЯ(2017, 1, 5, 0, 0, 0) КАК Начало,
ДАТАВРЕМЯ(2017, 1, 10, 0, 0, 0) КАК Конец,
ЛОЖЬ КАК Статус
ПОМЕСТИТЬ ВТ
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
ДАТАВРЕМЯ(2017, 1, 11, 0, 0, 0),
ДАТАВРЕМЯ(2017, 1, 20, 0, 0, 0),
ИСТИНА
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
ДАТАВРЕМЯ(2017, 1, 13, 0, 0, 0),
ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0),
ИСТИНА
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
ДАТАВРЕМЯ(2017, 2, 2, 0, 0, 0),
ДАТАВРЕМЯ(2017, 2, 10, 0, 0, 0),
ИСТИНА
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
ДАТАВРЕМЯ(2017, 2, 12, 0, 0, 0),
ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0),
ИСТИНА
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
ДАТАВРЕМЯ(2017, 2, 18, 0, 0, 0),
ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0),
ЛОЖЬ;
Наиболее эффективный способ избежать сложных вычислительных запросов — правильно спроектировать хранение данных. В платформе 1С для работы с состояниями во времени предназначен периодический регистр сведений.
Если хранить в регистре сведений только момент изменения состояния (реквизит Период) и само значение Состояние, то реквизит «ДатаЗавершения» становится не нужен. Дата завершения текущей записи автоматически считается датой начала следующей записи минус один день.
В этом случае получение актуального состояния на любую дату выполняется простым обращением к виртуальной таблице СрезПоследних, а получение истории изменений — обычным выбором записей регистра.
Если изменить структуру данных нельзя и требуется преобразовать таблицу исключительно средствами языка запросов 1С, разберем по шагам базовый алгоритм:
ВЫБОР КОГДА. Для дат окончания рассчитываем дату следующего дня через функцию ДОБАВИТЬКДАТЕ(Дата, ДЕНЬ, 1).ЛОЖЬ с помощью функции ЕСТЬNULL.Поскольку алгоритмы слияния интервалов в языке запросов 1С требуют соединений таблиц по условиям неравенства (что создает высокую нагрузку на СУБД при больших объемах данных), на практике часто применяют программную обработку:
Выгружаем результат первичного запроса в объект ТаблицаЗначений, сортируем по дате начала и обходим массив записей в цикле. Такой подход позволяет за один проход объединить накладывающиеся отрезки, вставить недостающие периоды «Нет» и сформировать итоговую таблицу без нагрузки на базу данных.