【问题标题】:Django workaround to use window function call in an aggregate function?Django 解决方法在聚合函数中使用窗口函数调用?
【发布时间】:2021-07-27 18:38:50
【问题描述】:

我正在尝试计算客户的订单频率。

首先使用窗口函数获取上一个订单日期,然后注释自上次订单以来的天数。

from django.db.models import Avg, F, Window
from django.db.models.functions import ExtractDay, Lag, TruncDate

orders = (
    Order.objects
    .annotate(
        prev_order_date=Window(
            expression=Lag('paid_at', 1),
            partition_by=[F('customer_email')],
            order_by=F('paid_at').asc(),
        ),
        days_since_last=ExtractDay(
            TruncDate('paid_at') - TruncDate('prev_order_date')
        ),
    )
)

然后在计算平均频率之前按customer_email分组。

customer_data = (
    orders.values('customer')
    .annotate(avg_frequency=Avg('days_since_last'))
)

不幸的是,这会引发错误。有谁知道解决方法或知道计算平均频率的替代方法?

psycopg2.errors.GroupingError: aggregate function calls cannot contain window function calls

【问题讨论】:

    标签: django postgresql


    【解决方案1】:

    我找到了django-ctethrough this answer

    加入订单id,然后确保在分组之前注释窗口函数的结果。

    from django_cte import CTEManager, With
    
    class OrderCTE(Order):
        objects = CTEManager()
    
        class Meta:
            proxy = True
    
    orders = With(
        Order.objects
        .annotate(
            prev_order_date=Window(
                expression=Lag('paid_at', 1),
                partition_by=[F('customer_email')],
                order_by=F('paid_at').asc(),
            ),
            days_since_last=ExtractDay(
                TruncDate('paid_at') - TruncDate('prev_order_date')
            ),
        )
    )
    
    customer_data = list(
        orders.join(OrderCTE, id=orders.col.id)
        .with_cte(orders)
        .annotate(days_since_last=orders.col.days_since_last)
        .values('customer_email')
        .order_by('customer_email')
        .annotate(
            avg_frequency=Avg('days_since_last'),
        )
        .values_list(
            'customer_email',
            'avg_frequency',
        )
    )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-27
      • 1970-01-01
      • 2019-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-29
      相关资源
      最近更新 更多