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.

  1. A new annotation that is equal to the date_time of the session when dt_difference is greater than one day, null otherwise.
  2. 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.

"2021-07-03 22:30:00+10" "01:29:00"null"2021-07-03 19:45:00+10""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""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""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""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""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""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""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""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""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""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"
id дата_время prev_date_tim dt_difference start_group start_dt
577 "2021-07-03 23:59:00+10"
574
576
575
572
573
580
579
578
571
569
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 сгруппировать их по желанию, с близлежащими сессиями с промежутком в день и более в обе стороны

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

Вернуться на верх