Использование Django ORM для суммирования аннотированных запросов
Я использую Django в сочетании с TimescaleDB для обработки данных об энергии от установок pv. Теперь я хочу вычислить, сколько энергии выработали несколько установок за определенный промежуток времени (обычно за день). Установки записывают новые значения в таблицу, которая выглядит следующим образом:
| клиент | datasource | значение | timestamp |
|---|---|---|---|
| 1 | 1 | 1 | 01.05.22 10:00 |
| 1 | 1 | 5 | 01.05.22 18:00 |
| 1 | 2 | 3 | 01.05.22 09:00 |
| 1 | 2 | 9 | 01.05.22 17:00 |
| 1 | 1 | 5 | 02.05.22 10:00 |
| 1 | 1 | 12 | 02.05.22 18:00 |
| 1 | 2 | 9 | 02.05.22 09:00 |
| 1 | 2 | 16 | 02.05.22 17:00 |
Теперь я хотел бы получить общий дневной прирост значений (так, для каждого дня: Last Entry Value - (минус) First Entry Value) для каждого клиента (что означает, суммировать ежедневные генерируемые значения энергии из всех источников данных, которые принадлежат клиенту).
В приведенном выше примере это было бы для клиента 1:
- День 01.05.22:
- Суточный прирост источника данных 1: 5 - 1 = 4
- Дневной прирост источника 2: 9 - 3 = 6
- Общий: 4 + 6 = 10
- День 02.05.22:
- Ежедневный прирост источника данных 1: 12 - 5 = 7
- Дневной прирост источника 2: 16 - 9 = 7
- Общий: 7 + 7 = 14
Результат должен выглядеть следующим образом:
| customer | timestamp | value |
|---|---|---|
| 1 | 01.05.22 00:00 | 10 |
| 1 | 02.05.22 00:00 | 14 |
Сейчас в коде я имею следующее:
dpes = (DataPointEnergy.timescale
.filter(source__in=datasources, time__range=(_from, _to))
.values('source', interval_end=timebucket)
.order_by('interval_end')
.annotate(value=Last('value', 'time') - First('value', 'time'))
.values('interval_end', 'value', 'source')
)
Что дает мне следующий результат:
{'source': 16, 'timestamp': datetime.datetime(2022, 1, 9, 0, 0, tzinfo=<UTC>), 'value': 2.0}
{'source': 17, 'timestamp': datetime.datetime(2022, 1, 9, 0, 0, tzinfo=<UTC>), 'value': 2.0}
{'source': 16, 'timestamp': datetime.datetime(2022, 1, 10, 0, 0, tzinfo=<UTC>), 'value': 2.0}
{'source': 17, 'timestamp': datetime.datetime(2022, 1, 10, 0, 0, tzinfo=<UTC>), 'value': 2.0}
{'source': 16, 'timestamp': datetime.datetime(2022, 1, 11, 0, 0, tzinfo=<UTC>), 'value': 2.0}
{'source': 17, 'timestamp': datetime.datetime(2022, 1, 11, 0, 0, tzinfo=<UTC>), 'value': 2.0}
Однако мне все равно придется группировать результаты по временной метке и суммировать столбец значений (что я делаю сейчас с помощью Pandas). Есть ли возможность позволить базе данных сделать эту работу?
Я попытался использовать другой .annotate() для суммирования значений, но это приводит к ошибке:
django.core.exceptions.FieldError: Cannot compute Sum('value'): 'value' is an aggregate