В каких бизнес-задачах 1С требуется определять интервалы времени и как оптимизировать такие запросы?

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

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

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

Базовый механизм: как это выглядит в запросе 1С

Посмотрим на пример типичной реализации. Допустим, у нас есть таблица, содержащая множество дат документов, установки цен или статусов. Чтобы получить интервал постоянства цены (от даты начала действия текущей цены до даты начала действия следующей), мы обычно используем самосоединение таблицы. Рассмотрим классический запрос:


ВЫБРАТЬ 
    ИсходнаяТаблицаСДатами.Период КАК Период
ПОМЕСТИТЬ ВТ_Даты 
ИЗ 
    &ИсходнаяТаблицаСДатами КАК ИсходнаяТаблицаСДатами;

ВЫБРАТЬ 
    ВТ_Даты1.Период Как НачалоПериода, 
    МИНИМУМ(ВТ_Даты2.Период) КАК КонецПериода 
ИЗ 
    ВТ_Даты КАК ВТ_Даты1 
        ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Даты КАК ВТ_Даты2 
        ПО ВТ_Даты2.Период > ВТ_Даты1.Период 
СГРУППИРОВАТЬ ПО 
    ВТ_Даты1.Период;

Конструкция ЛЕВОЕ СОЕДИНЕНИЕ по условию > (или <) позволяет найти для каждой даты ближайшую следующую за ней точку на временной оси. Однако, при больших объемах данных такое соединение таблицы самой с собой начинает работать недопустимо долго из-за квадратичной сложности алгоритма (серверу СУБД приходится перебирать огромное количество комбинаций). Тем не менее, потребность в таких данных огромна.

Практические бизнес-задачи, требующие разбиения на интервалы

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

  1. Анализ "Динамических срезов последних": Стандартный виртуальный табличный метод СрезПоследних у периодических регистров сведений позволяет получить данные только на конкретную дату (параметр). Если руководителю требуется отчет по фактической численности сотрудников или изменению цен за каждый месяц в динамике, вызывать срез в цикле — плохая практика. Запрос с определением интервалов позволяет получить динамический срез за один проход базы.
  2. Системы контроля и управления доступом (СКУД) и учет рабочего времени: Расчет времени нахождения сотрудника на территории. Вход и выход образуют интервалы. Требуется анализировать краевые условия, например, объединять входы с интервалом в секунду в один, отсекать зависшие статусы (вход сегодня, а выход завтра), а также учитывать ночные и дневные смены с разными тарифами оплат.
  3. Кадровый учет (ЗУП): Вычисление экономии бюджета заработной платы. Например, отслеживание периодов, когда должность была в штатном расписании, но фактически человек еще не был принят на работу (вакансия простаивала).
  4. Логистика и управление цепочками поставок: Расчет сроков доставки. Когда партия едет из другой страны, она меняет транспорт в ключевых узлах. Просчет прогнозной даты прибытия строится на цепочке плановых интервалов прохождения участков.
  5. Контроль транспорта и расхода ГСМ: Вычисление пробега и расхода топлива по путевым листам. Автомобиль выезжает на маршруты в разные дни с разными показателями одометра. Разбивая эти данные на интервалы "выезд - следующий выезд", мы можем легко вычислить пробег между точками даже при проведении документов задним числом.
  6. Контроль торговых представителей (GPS трекинг): Определение максимального времени присутствия агента на торговой точке, вычисление времени на дорогу между точками и автоматическое вырезание времени на обеденный перерыв.
  7. Финансовая и складская аналитика: Расчет всех видов оборачиваемости (дебиторской задолженности, запасов, денежных средств), расчет дивидендов, начисление процентов по вкладам за точное количество дней и биллинг услуг (связь, интернет, аренда).

Дополнительные сложные задачи работы с периодами

Выясним причину, почему простым запросом не всегда удается обойтись. Разберем более сложные вариации задач с интервалами:

  1. Поиск пропусков (Gaps and Islands): Выявление удаленных документов, кассовых чеков или пропущенных дней в расписании. После преобразования строковых номеров в числовые (отсекая префиксы), мы ищем интервалы между номерами. Если разница между началом и концом интервала больше единицы — обнаружена потеря данных.
  2. Схлопывание непрерывных периодов: При аренде оборудования или гостиничных номеров, если клиент бронировал объект сначала с 1 по 2 число, а затем продлил с 3 по 4, системе требуется объединить это в единый интервал с 1 по 4 число.
  3. Учет SLA и "вырезание" дат: Расчет времени реакции технической поддержки. Берется общий астрономический интервал, из которого вырезаются (исключаются) выходные дни, нерабочие часы и праздники по производственному календарю.
  4. Контроль плотности расписания: Для клиник и учебных центров нужно проверять пересечение интервалов. Система должна контролировать, чтобы на один и тот же временной слот не было записано пациентов сверх заданного лимита.

Архитектурные решения проблемы производительности

Проанализируем ситуацию: в крупных компаниях (например, штат более 1000 сотрудников или миллионы чеков) расчет интервалов динамическим запросом с ЛЕВОЕ СОЕДИНЕНИЕ "вешает" сервер СУБД. Выполнение может занимать минуты. Как с этим бороться? Рассмотрим несколько надежных подходов:

1. Изменение архитектуры хранения данных

Вместо того чтобы вычислять интервалы "на лету" в момент формирования отчета, мы можем сохранять их заранее. Добавляется новый периодический регистр сведений (или накопления), который хранит уже готовые показатели в нужной периодичности (например, по дням). Заполнение этого регистра производится специальным регламентным заданием в фоновом режиме по ночам. В случае необходимости перерасчета из-за изменения документов "задним числом" регистр точечно перезаполняется. При таком подходе время формирования тяжелых отчетов сокращается с минут до долей секунды.

2. Добавление реквизита "Дата окончания"

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

3. Программный обход вместо запроса

Для задач типа СКУД (вход-выход), где нужно анализировать много краевых логических условий, использовать сложный запрос нерационально. Зачастую гораздо эффективнее выбрать все события линейным запросом, отсортировать их по времени и обработать за один проход по выборке в коде модуле 1С. Алгоритмы сложности O(N) в оперативной памяти сервера 1С отработают быстрее, чем тяжеловесные соединения таблиц на стороне СУБД.

4. Метод фиксации производительности "в моменте"

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

Современные технические решения в платформе 1С

Рассмотрим подробнее новые возможности, которые разработчики получили в последних версиях платформы 1С:Предприятие.

Оконные функции: Начиная с версии платформы 8.3.20, в язык запросов 1С были добавлены оконные функции. Это кардинально меняет правила игры. Теперь для получения следующего или предыдущего значения (начала нового интервала) нам больше не нужно соединять таблицу саму с собой по условию "больше-меньше". Мы можем использовать оконные функции смещения (аналоги LEAD и LAG в SQL). Получение даты следующего события в рамках группировки (например, по конкретному товару) выполняется линейно, за один проход базы данных сервером СУБД. Это решает проблему производительности на корню.

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

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

← На главную