У меня есть таблица, содержащая ряд записей, которые относятся к периодам времени (в частности, время, отработанное для клиента):
task_time:
id | start_time | end_time | client (fk)
1 08/12/2011 14:48 08/12/2011 14:50 2
Я пытаюсь объединить все время, отработанное для данного клиента, из моего приложения Django:
time_worked_aggregate = models.TaskTime.objects.\
filter(client = some_client_id).\
extra(select = {'elapsed': 'SUM(task_time.end_time - task_time.start_time)'}).\
values('elapsed')
if len(time_worked_aggregate) > 0:
time_worked = time_worked_aggregate[0]['elapsed'].total_seconds()
else:
time_worked = 0
Это выглядит не элегантно, но действительно работает . Или, по крайней мере, я подумал: получается, что он отлично работает на базе данных PostgreSQL, но когда я перехожу на SQLite, все умирает.
Небольшое копание показывает, что причина этого в том, что DateTime
не являются первоклассными данными в SQLite. Следующий необработанный запрос SQLite выполнит мою работу:
SELECT SUM(strftime('%s', end_time) - strftime('%s', start_time)) FROM task_time WHERE ...;
У меня такой вопрос:
- Пример Python выше кажется окольным. Можем ли мы сделать это более элегантно?
- Что еще более важно на данном этапе, можем ли мы сделать это так, чтобы это работало как на Postgres, так и на SQLite? В идеале я бы не хотел писать необработанные SQL-запросы и включать серверную часть базы данных, которая оказывается на месте; в общем Джанго очень хорошо защищает нас от этого. Есть ли у Django разумная абстракция для этой операции? Если нет, то какой для меня разумный способ сделать условное переключение на бэкэнде?
Я должен упомянуть для контекста, что в наборе данных много тысяч записей; следующее не очень практично:
sum([task_time.end_date - task_time.start_date for task_time in models.TaskTime.objects.filter(...)])