Поиск пробелов в метках времени для нескольких пользователей в PostgreSQL - PullRequest
1 голос
/ 07 февраля 2020

Я работаю с набором данных, содержащим время заезда и выезда для нескольких офисных помещений за последние 5 лет. Один из проектов, над которым меня попросили поработать, - это подсчет времени, в течение которого каждая комната занята и свободна в различных временных интервалах (ежедневно, еженедельно, ежемесячно и т. Д. 1016 *), исходя из нормальных рабочих часов (с 8:00 до 17:00). Пример набора данных за два дня выглядит следующим образом:

room_id         start_dt                end_dt
Room: Room 3    2019-05-04 09:00:00     2019-05-04 11:30:00
Room: Room 3    2019-05-04 11:30:00     2019-05-04 12:15:00
Room: Room 3    2019-05-04 12:30:00     2019-05-04 13:00:00
Room: Room 3    2019-05-05 09:00:00     2019-05-05 13:00:00
Room: Room 4    2019-05-04 08:00:00     2019-05-04 09:00:00
Room: Room 4    2019-05-04 09:00:00     2019-05-04 11:00:00
Room: Room 4    2019-05-04 14:00:00     2019-05-04 16:00:00
Room: Room 4    2019-05-05 08:30:00     2019-05-05 09:30:00

Я позаимствовал и изменил некоторый код, написанный в предыдущем сообщении StackOverflow @Branko Dimitrijevi c (полное сообщение: SQL Запрос, чтобы показать разрывы между несколькими диапазонами дат ), чтобы попытаться обработать несколько разных комнат. Ниже мой модифицированный код с двумя экземплярами room_id в предложении SELECT для целей отладки:

SELECT t1.room_id, t2.room_id, end_dt, start_dt, start_dt - end_dt as gap_dur
FROM
    (
        SELECT DISTINCT room_id, start_dt, ROW_NUMBER() OVER (ORDER BY start_dt) RN
        FROM my_table T1
        WHERE
            NOT EXISTS (
                SELECT *
                FROM my_table T2
                WHERE (T1.start_dt > T2.start_dt and t1.resource = t2.resource)
                    AND (T1.start_dt < T2.end_dt and t1.resource = t2.resource)
            )
        ) T1
    JOIN (
        SELECT DISTINCT resource, end_dt, ROW_NUMBER() OVER (ORDER BY end_dt) RN
        FROM my_table T1
        WHERE
            NOT EXISTS (
                SELECT *
                FROM my_table T2
                WHERE (T1.end_dt > T2.start_dt and t1.resource = t2.resource)
                    AND (T1.end_dt < T2.end_dt and t1.resource = t2.resource)
            )
    ) T2
    ON T1.RN - 1 = T2.RN
WHERE
    end_dt < start_dt

И это вывод, который я получаю:

room_id         room_id         end_dt                  start_dt                gap_dur
Room: Exam 4    Room: Exam 4    2019-05-04 16:00:00     2019-05-05 08:30:00     16:30:00
Room: Exam 4    Room: Exam 3    2019-05-04 13:00:00     2019-05-04 14:00:00     01:00:00
Room: Exam 3    Room: Exam 3    2019-05-04 12:15:00     2019-05-04 12:30:00     00:15:00

Однако, это становится перепутаны между различными комнатами, и я не знаю, как реализовать ограничения рабочего дня, такие как нахождение промежутков времени между 8:00 и первым запланированным событием. Ниже приведен оптимальный вывод или, по крайней мере, формат данных, который можно было бы использовать для вычисления статистики, которая мне понадобилась бы для некоторых простых скриптов GROUP BY:

room_id         end_dt                  start_dt                gap_dur
Room: Exam 3    2019-05-04 08:00:00     2019-05-04 09:00:00     01:00:00
Room: Exam 3    2019-05-04 12:15:00     2019-05-04 12:30:00     00:15:00
Room: Exam 3    2019-05-04 13:00:00     2019-05-04 17:00:00     04:00:00
Room: Exam 3    2019-05-05 08:00:00     2019-05-05 09:00:00     01:00:00
Room: Exam 3    2019-05-05 13:00:00     2019-05-05 17:00:00     04:00:00
Room: Exam 4    2019-05-04 11:00:00     2019-05-04 14:00:00     03:00:00
Room: Exam 4    2019-05-04 16:00:00     2019-05-04 17:00:00     01:00:00
Room: Exam 4    2019-05-05 08:00:00     2019-05-05 08:30:00     00:30:00
Room: Exam 4    2019-05-05 09:30:00     2019-05-05 17:00:00     09:30:00

Любая помощь по этому вопросу будет принята с благодарностью и рада предоставьте дополнительную информацию, если это поможет!

1 Ответ

0 голосов
/ 07 февраля 2020

Один из проектов, над которыми меня попросили поработать, - это подсчет времени, в течение которого каждая комната занята и свободна в различных временных интервалах (ежедневно, еженедельно, ежемесячно и т. Д. c.), Исходя из нормальных рабочих часов ( 8 утра до 5 вечера).

Основываясь на данных выборки, два предположения представляются разумными:

  • Периоды "занятости" не перекрываются.
  • Периоды "занятости" все в течение одного дня.

Если это не так, я бы посоветовал вам задать НОВЫЙ вопрос с соответствующими пояснениями и образцами данных.

Тогда вычисление довольно просто для данный день:

select date_trunc('day', start_dt),
       sum( least(extract(epoch from end_dt), v.epoch2) - 
            greatest(extract(epoch from start_dt), epoch1)
          ) as busy_seconds,
       (epoch2 - epoch1 -
        sum( least(extract(epoch from end_dt), v.epoch2) - 
             greatest(extract(epoch from start_dt), epoch1)
           )
       ) as free_seconds
from rooms r cross join
     (values (extract(epoch from date_trunc('day', start_dt) + interval '8 hour'),
              extract(epoch from date_trunc('day', start_dt) + interval '17 hour')
             )
     ) v(epoch1, epoch2)                  
group by date_trunc('day', start_dt)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...