Django группирует соседние строки на основе времени суток
В модели Django, которая хранит дату события, я хотел бы группировать строки рядом по времени даты. Для пояснения, каждый объект имеет поле date_time, и я могу довольно легко найти промежуток между объектами по времени даты с помощью:
# We want a minimum date_time as the default for prev_date_time
# but because Session.date_time is a DateFimeField and TZ aware
# Django requires teh default to be TZ aware. And datetime.min
# cannot be made TZ awre (it crashes), adding one day prevents
# that crash and works and serves our purposes.
min_date_time = make_aware(datetime.min + timedelta(days=1), "UTC")
sessions = Session.objects.all().annotate(
prev_date_time=Window(
expression=Lead('date_time', default=min_date_time),
order_by=F('date_time').desc()
),
dt_difference=F('date_time') - F('prev_date_time')
)
Это работает блестяще.
Теперь я хочу сгруппировать эти сессии так, чтобы любая сессия с разницей dt_difference более 1 дня отмечала границу группы.
Я представляю, что две новые аннотации могли бы сделать этот трюк, но я испытываю трудности с их написанием и в идеале хотел бы сделать это, не прибегая к сырому SQL.
- A new annotation that is equal to the date_time of the session when dt_difference is greater than one day, null otherwise.
- A new annotation that fills all these nulls with the first non-null value (in the direction away from the gap) with this date time.
Лучше всего проиллюстрировать на примере. Я извлекаю некоторые примеры данных из этой таблицы следующим образом и иллюстрирую, в которых я показываю время date_time и prev_date_time и dt_difference в соответствии с аннотациями выше, а также иллюстрирую две новые аннотации, start_group и stat_dt.
| id | дата_время | prev_date_tim | dt_difference | start_group | start_dt | 577 | "2021-07-03 23:59:00+10" | "2021-07-03 22:30:00+10" "01:29:00"null"2021-07-03 19:45:00+10"
|---|---|---|---|---|---|
| 574 | "2021-07-03 22:30:00+10""2021-07-03 22:30:00+10" "00:00:00"null"2021-07-03 19:45:00+10"|||||
| 576 | "2021-07-03 22:30:00+10""2021-07-03 21:00:00+10" "01:30:00"null"2021-07-03 19:45:00+10"|||||
| 575 | "2021-07-03 21:00:00+10""2021-07-03 19:45:40+10""01:14:20"null"2021-07-03 19:45:00+10"|||||
| 572 | "2021-07-03 19:45:40+10""2021-07-03 19:45:00+10" "00:00:40"null"2021-07-03 19:45:00+10"|||||
| 573 | "2021-07-03 19:45:00+10""2021-06-19 22:15:00+10" "13 дней 21:30:00""2021-07-03 19:45:00+10""2021-07-03 19:45:00+10"|||||
| 580 | "2021-06-19 22:15:00+10""2021-06-19 20:45:00+10" "01:30:00"null"2021-06-19 19:15:00+10"|||||
| 579 | "2021-06-19 20:45:00+10""2021-06-19 19:15:00+10" "01:30:00"null"2021-06-19 19:15:00+10"|||||
| 578 | "2021-06-19 19:15:00+10""2021-06-05 23:59:00+10" "13 дней 19:16:00""2021-06-19 19:15:00+10""2021-06-19 19:15:00+10"|||||
| 571 | "2021-06-05 23:59:00+10""2021-06-05 22:00:00+10" "01:59:00"null"2021-06-05 19:00:00+10"|||||
| 569 | "2021-06-05 22:00:00+10""2021-06-05 21:30:00+10" "00:30:00"null"2021-06-05 19:00:00+10"|||||
| 570 | "2021-06-05 21:30:00+10" | "2021-06-05 21:10:00+10" | "00:20:00" | null | "2021-06-05 19:00:00+10" |
| 568 | "2021-06-05 21:10:00+10" | "2021-06-05 19:00:00+10" | "02:10:00" | null | "2021-06-05 19:00:00+10" |
| 567 | "2021-06-05 19:00:00+10" | "2021-05-22 18:15:00+10" | "14 days 00:45:00" | "2021-06-05 19:00:00+10" | "2021-06-05 19:00:00+10" |
Теперь start_group не нужна сама по себе, я просто представляю ее как промежуточный элемент, который, возможно, легко аннотировать. Целью является start_dt, по которому мы можем затем GROUP_BY сгруппировать их по желанию, с близлежащими сессиями с промежутком в день и более в обе стороны
У меня есть ощущение, что это лучше всего сделать и, вероятно, возможно с помощью аннотаций, так что один запрос к базе данных может затем вернуть агрегированную информацию о сгруппированных сессиях.