Как найти наиболее загруженный день в отеле: решение задачи о пересечении интервалов в 1С

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

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

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

Постановка задачи и логика решения

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

Основная идея решения заключается в преобразовании интервалов в «события». Каждое проживание — это два события:

  1. Заезд: в этот день количество гостей увеличивается на 1 (+1).
  2. Отъезд: в этот день (или на следующий, в зависимости от логики учета) количество гостей уменьшается на 1 (-1).

Суммируя эти изменения в хронологическом порядке, мы получаем «нарастающий итог», который и показывает количество проживающих в каждый конкретный момент времени.

Решение через классический запрос (соединение таблицы «самой с собой»)

Проанализируем самый распространенный метод, который подходит для старых версий платформы и универсален для большинства СУБД. Процесс разделяется на несколько этапов.

Этап 1: Подготовка таблицы событий. Мы объединяем данные о приезде и отъезде в одну временную таблицу.


ВЫБРАТЬ
    ТЧ.ДатаПриезда КАК Дата,
    1 КАК Изменение
ПОМЕСТИТЬ ВТ_События
ИЗ
    Документ.Расписание КАК ТЧ

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    ТЧ.ДатаОтъезда,
    -1
ИЗ
    Документ.Расписание КАК ТЧ
;

Этап 2: Группировка по датам. В один день может быть несколько заездов и выездов, поэтому схлопываем данные.


ВЫБРАТЬ
    ВТ.Дата КАК Дата,
    СУММА(ВТ.Изменение) КАК СуммаИзменений
ПОМЕСТИТЬ ВТ_ИзмененияПоДням
ИЗ
    ВТ_События КАК ВТ
СГРУППИРОВАТЬ ПО
    ВТ.Дата
;

Этап 3: Расчет нарастающего итога. Теперь нам нужно для каждой даты посчитать сумму всех изменений, которые произошли до этой даты включительно. Для этого мы соединяем таблицу ВТ_ИзмененияПоДням саму с собой по условию Т1.Дата >= Т2.Дата.


ВЫБРАТЬ ПЕРВЫЕ 1
    Т1.Дата КАК ДеньРаботы,
    СУММА(Т2.СуммаИзменений) КАК КоличествоГостей
ИЗ
    ВТ_ИзмененияПоДням КАК Т1
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_ИзмененияПоДням КАК Т2
        ПО Т1.Дата >= Т2.Дата
СГРУППИРОВАТЬ ПО
    Т1.Дата
УПОРЯДОЧИТЬ ПО
    КоличествоГостей УБЫВ,
    ДеньРаботы ВОЗР

Этот запрос выведет ровно один день с максимальной загрузкой. Использование УПОРЯДОЧИТЬ ПО КоличествоГостей УБЫВ, ДеньРаботы ВОЗР гарантирует, что при равенстве максимумов мы получим самую раннюю дату.

Современный подход: Оконные функции (Платформа 8.3.24+)

Если ваша информационная база работает на современной версии платформы, расчет нарастающего итога можно значительно упростить и ускорить. Использование оконных функций избавляет от тяжелого соединения O(n^2), которое при 10 000 записей может выполняться ощутимо долго.

Рассмотрим, как изменится финальная часть запроса с применением конструкции ОБРАБОТКА ИЗМЕНЕНИЙ:


ВЫБРАТЬ
    Т.Дата КАК ДеньРаботы,
    СУММА(Т.СуммаИзменений) ОБРАБОТКА ИЗМЕНЕНИЙ 
        ПОРЯДОК ПО Т.Дата КАК КоличествоГостей
ПОМЕСТИТЬ ВТ_Итоги
ИЗ
    ВТ_ИзмененияПоДням КАК Т
;

ВЫБРАТЬ ПЕРВЫЕ 1
    ВТ.ДеньРаботы,
    ВТ.КоличествоГостей
ИЗ
    ВТ_Итоги КАК ВТ
УПОРЯДОЧИТЬ ПО
    ВТ.КоличествоГостей УБЫВ,
    ВТ.ДеньРаботы ВОЗР

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

Проблема «пустых дней» и использование таблицы чисел

Проанализируем важный нюанс, упомянутый участниками обсуждения. Что если максимальная загрузка длилась 3 дня, но во второй день никто не заезжал и не уезжал? В нашей таблице ВТ_ИзмененияПоДням этой даты просто не будет, так как там фиксируются только моменты изменений.

Для решения этой проблемы в 1С применяют методику «Календаря» или «Таблицы чисел». Разберем по шагам, как заполнить дыры в периоде:

  1. Создаем временную таблицу с цифрами от 0 до 9.
  2. Путем кросс-соединения (умножения) этой таблицы самой на себя получаем последовательность чисел (0, 1, 2... 1000 и более).
  3. Добавляем эти числа в виде дней к начальной дате работы отеля.
  4. Левым соединением присоединяем наши данные о гостях к этому полному календарю.

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

Тонкости учета даты отъезда

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

Ситуация А: Клиент уезжает 8-го числа вечером. Он занимал место весь день 8-го числа. В этом случае в запросе дата отъезда используется «как есть».

Ситуация Б: Клиент уезжает 8-го числа в 10:00, а в 14:00 на его место заезжает другой. Если мы просто прибавим +1 (заезд) и -1 (отъезд), то в отчете на 8-е число у нас получится корректное сальдо. Но если мы хотим считать именно «ночевки», то событие выезда часто смещают или корректируют логику запроса так, чтобы выехавший утром не суммировался с заехавшим днем.

Для корректного решения в рамках задачи «наибольшее количество клиентов за день» обычно принимается, что клиент был в отеле и в день приезда, и в день отъезда. Если же логика иная, то в запросе к дате отъезда следует прибавлять 1 день, чтобы «минусовать» остаток только со следующего дня после выезда.

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

Чтобы программа работала быстро даже при большом объеме данных (сотни тысяч записей), придерживайтесь следующих правил:

Таким образом, мы рассмотрели комплексный подход к поиску пиковых значений. Сочетание правильной подготовки данных (событийной модели) и современных инструментов платформы 1С позволяет решать такие задачи эффективно и элегантно.

← На главную