DjangoGenerateSeries多次返回同一行

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

我有一个带有starts_at、repeat_duration的预约模型

我想注释从生成的系列返回的重复值和持续时间字段直到结束日期

因此,如果预约日期为 14-07-2024,则 end_date 为 25-07-2024,持续时间为 3 天 它返回 14, 17, 20, 23 作为数组注释

但我得到的是同一个对象,返回多次,每次它都有系列结果的一个值

对于该示例,每个值将返回四次一,并且重复天数将是该值

object_1.repeat_days = 14 object_2.repeat_days = 17

如何让它只返回一个对象和数组形式的值

尝试用 arrayagg 来包装GenerateSeries,但我得到了

聚合函数调用不能包含设置返回函数调用

class AppointmentQuerySet(models.QuerySet):
    def annotate_repeated_days(self, end_date):
        return self.annotate(
            repeat_dates=ArrayAgg(
                GenerateSeries(
                    models.F("starts_at"), models.F("repeat_duration"), end_date
                )
            )
        )

功能:

from django.db import models

class GenerateSeries(models.Func):
    function = 'generate_series'
    output_field = models.DateTimeField()

    def __init__(self, start, step, stop, **extra):
        expressions = [
            start,
            stop,
            step
        ]
        super().__init__(*expressions, **extra)

有什么想法吗?

django postgresql
1个回答
0
投票

这会导致错误指出的非法 SRF-in-aggregate 构造

array_agg(generate_series(starts_at,end_date,repeat_duration)) as repeat_dates

但是,通过将返回集合的函数移动到子查询中并让聚合函数从中提取行,可以很容易地避开限制:

(select array_agg(n) as repeat_dates 
 from generate_series(starts_at,end_date,repeat_duration) as g(n))

您可以通过设置

Func.subquery=True
:

让 Django 使用子查询语法
from django.db import models

class GenerateSeries(models.Func):
    subquery = True ###################### here
    function = 'generate_series'
    output_field = models.DateTimeField()

    def __init__(self, start, step, stop, **extra):
        expressions = [#side-note: why reorder Postgres' (stOp,stEp) to (stEp,stOp)?
            start,
            stop,
            step
        ]
        super().__init__(*expressions, **extra)

Django 检查here 并且它会影响决策here:

   # Decide if we need to use a subquery.
   #
   # Existing aggregations would cause incorrect results as
   # get_aggregation() must produce just one result and thus must not use
   # GROUP BY.
   #
   # If the query has limit or distinct, or uses set operations, then
   # those operations must be done in a subquery so that the query
   # aggregates on the limit and/or distinct results instead of applying
   # the distinct and limit after the aggregation.
© www.soinside.com 2019 - 2024. All rights reserved.