如何为Window函数构建Django查询表达式

问题描述 投票:0回答:1

我有postgres查询,我想用Django QuerySet构建器来表示它

我有一张桌子: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表达式

另一个问题 - 有些日子没有数据,它们没有出现在我的图表上

django python-3.x postgresql
1个回答
0
投票

像你这样的嵌套查询无法在ORM语法中轻松定义。 Subquery仅限于返回单个值的相关子查询。这通常会导致您可以在SQL中轻松表达的查询的扭曲和低效的ORM变通方法。

在这种情况下,您可以使用两个Window函数和distinct子句。

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中,你可以使用calendar table

© www.soinside.com 2019 - 2024. All rights reserved.