У меня есть таблица пар время / продолжительность. Время указано с 15-минутными интервалами с возможными промежутками.Длительности представляют собой значения от 5 минут до 15 минут:
slot_ts | duration
------------------- |----------
2019-01-28 07:45:00 | 00:05:00
2019-01-28 08:00:00 | 00:10:00
2019-01-28 08:15:00 | 00:10:00
2019-01-28 08:30:00 | 00:10:00
2019-01-28 08:45:00 | 00:15:00
2019-01-28 09:30:00 | 00:15:00
2019-01-28 09:45:00 | 00:15:00
2019-01-28 10:00:00 | 00:15:00
2019-01-28 10:15:00 | 00:15:00
2019-01-28 10:30:00 | 00:15:00
2019-01-28 11:00:00 | 00:15:00
2019-01-28 11:15:00 | 00:15:00
2019-01-28 11:30:00 | 00:10:00
2019-01-28 11:45:00 | 00:15:00
2019-01-28 12:00:00 | 00:15:00
Обратите внимание на промежутки времени с 8:45 до 9:30.И с 10:30 до 11:00.
Концепция заключается в каждом отдельном интервале (который охватывает 15-минутный период), показанная продолжительность представляет собой доступное время, все еще находящееся в этом интервале.Так, например, в слоте 7:45 есть 5 минут, которые еще доступны в этом слоте (т. Е. 10 минут израсходованы).Если 15-минутный интервал времени отсутствует, это означает, что в этом интервале нет свободного времени.Так, например, для слотов 9:00, 9:15, 10:45 нет доступного времени.
Я хочу сгенерировать продолжительность работы для каждого временного интервала, где продолжительность работы сбрасывается на основе некоторыхКритерии.
Если какой-либо из этих критериев удовлетворен, продолжительность работы должна быть сброшена:
- Между слотами есть промежуток (например, 9:30 будеттребуется сброс)
- Следующая длительность составляет менее 15 минут (но включите эту следующую длительность в промежуточную сумму до сброса) - это в значительной степени означает, что при отсутствии разрыва длительность выполнения можетпродолжить для всех интервалов между текущей продолжительностью и продолжительностью, не равной 15 минутам включительно .Таким образом, продолжительность пробежки в 8:00 составит 20 минут, поскольку в 8:00 - 10 минут, а в 8:15 - 10 минут.
Изображения лучше, чем слова, так что вот пример того, что яm ищет:
slot_ts | duration | running_duration
------------------- |----------|------------------
2019-01-28 07:45:00 | 00:05:00 | 00:15:00
2019-01-28 08:00:00 | 00:10:00 | 00:20:00
2019-01-28 08:15:00 | 00:10:00 | 00:20:00
2019-01-28 08:30:00 | 00:10:00 | 00:25:00
2019-01-28 08:45:00 | 00:15:00 | 00:15:00
2019-01-28 09:30:00 | 00:15:00 | 01:15:00
2019-01-28 09:45:00 | 00:15:00 | 01:00:00
2019-01-28 10:00:00 | 00:15:00 | 00:45:00
2019-01-28 10:15:00 | 00:15:00 | 00:30:00
2019-01-28 10:30:00 | 00:15:00 | 00:15:00
2019-01-28 11:00:00 | 00:15:00 | 00:40:00
2019-01-28 11:15:00 | 00:15:00 | 00:25:00
2019-01-28 11:30:00 | 00:10:00 | 00:10:00
2019-01-28 11:45:00 | 00:15:00 | 00:30:00
2019-01-28 12:00:00 | 00:15:00 | 00:15:00
Обратите внимание, что в моем примере из реальной жизни эта таблица будет хранить эти значения «доступных слотов» в интервале 6 месяцев вместо промежутка времени от 7:45 до полудня Iв этом примере
I do имеет запрос, который работает, но он использует 2 субвыбора и 2 оконные функции.В моем примере с реальным миром я буду запрашивать тысячи строк, и это должно выполняться как можно быстрее.
Вот мой существующий запрос, Вы можете сделать лучше ??
SELECT
slot_ts,
duration,
COALESCE(
(
SELECT SUM(duration)
FROM available_slots
WHERE slot_ts >= x.slot_ts
AND slot_ts <=
(
SELECT slot_ts AS last_ts
FROM
(
SELECT *,
NOT COALESCE(lead(slot_ts) OVER (ORDER BY slot_ts) = slot_ts + '00:15:00', FALSE) AS cur_row_stop,
NOT COALESCE(lead(slot_ts) OVER (ORDER BY slot_ts) = slot_ts + '00:15:00', FALSE) OR duration < '00:15:00' AS prev_row_stop
FROM available_slots
) z
WHERE (cur_row_stop AND slot_ts = x.slot_ts) OR (prev_row_stop AND slot_ts > x.slot_ts)
ORDER BY slot_ts LIMIT 1
)
), duration) AS running_duration
FROM available_slots AS x
ORDER BY slot_ts ASC;
Вот sql fiddle вышеуказанной схемы таблицы и запроса.