Как построить Django Query Expression для оконной функции - PullRequest
0 голосов
/ 28 марта 2019

У меня есть запрос postgres, и я хочу представить его с помощью Django QuerySet Builder

У меня есть таблица: history_events

date -------------------------- amount
2019-03-16 16:03:11.49294+05    250.00
2019-03-18 14:56:30.224846+05   250.00
2019-03-18 15:07:30.579531+05   250.00
2019-03-18 20:52:53.581835+05   5.00
2019-03-18 22:33:21.598517+05   1000.00
2019-03-18 22:50:57.157465+05   1.00
2019-03-18 22:51:44.058534+05   2.00
2019-03-18 23:11:29.531447+05   255.00
2019-03-18 23:43:43.143171+05   250.00
2019-03-18 23:44:47.445534+05   500.00
2019-03-18 23:59:23.007685+05   250.00
2019-03-19 00:01:05.103574+05   255.00
2019-03-19 00:01:05.107682+05   250.00
2019-03-19 00:01:05.11454+05    500.00
2019-03-19 00:03:48.182851+05   255.00

, и мне нужно построить графику, используя эти данные с шагомпошаговое увеличение суммы суммы по датам

Этот SQL собирает правильные данные:

with data as (
  select
    date(date) as day,
    sum(amount) as day_sum
  from history_event
  group by day
)
select
  day,
  day_sum,
  sum(day_sum) over (order by day asc rows between unbounded preceding and current row)
from data

Но я не могу понять, как построить правильное выражение Queryset для этого

Другая проблема- нет данных за несколько дней, и они не отображаются на моем графике

1 Ответ

0 голосов
/ 28 марта 2019

Вложенные запросы, подобные вашему, не могут быть легко определены в синтаксисе ORM. Подзапрос ограничен коррелированными подзапросами, возвращающими одно значение. Это часто приводит к искаженным и неэффективным обходным решениям ORM для запросов, которые можно легко выразить в SQL.

В этом случае вы можете использовать две оконные функции в сочетании с отдельным предложением.

result = (Event.objects
    .values('date', 'amount')
    .annotate(day_sum=Window(
        expression=Sum('amount'),
        partition_by=[F('date')],
    ))
    .annotate(total=Window(
        expression=Sum('amount'),
        frame=RowRange(start=None, end=0),
        order_by=F('date').asc(),
    ))
    .distinct('date')       
    .order_by('date', '-total')
)

Вам необходимо заказать по '-total', иначе distinct отбрасывает неправильные строки, оставляя вам меньше правильных сумм в total.

Что касается пропущенных дней; SQL не имеет внутренней концепции календарей (и, следовательно, пропущенных дат), и если у вас нет большого количества данных, будет проще добавить пропущенные дни в цикл Python. В SQL вы можете сделать это с помощью календарной таблицы .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...