【问题标题】:Annotate + Distinct Not Implemented, Count a Distinct SubqueryAnnotate + Distinct 未实现,计算 Distinct 子查询
【发布时间】:2021-09-26 16:46:13
【问题描述】:

我有两个模型,RetailLocation 和 Transaction,它们分别共享一对多的关系。我试图注释一个零售位置有任意数量的交易的总天数(计数)。这样做时,我将 Transaction.date 字段过滤为 Date 而不是 Datetime,并尝试选择 DISTINCT 日期,但遇到错误“NotImplementedError: annotate() + distinct(fields) 未实现。

型号

class RetailLocation(models.Model):
    name = models.CharField(max_length=200, null=True)

class Transaction(models.Model):
    date = models.DateTimeField(null=True)
    r_loc = models.ForeignKey(RetailLocation, null=True, on_delete=models.SET_NULL)

尝试的代码

test = RetailLocation.objects.annotate(                                                    
    days_operating=Subquery(                                                     
        Transaction.objects.filter(r_loc=OuterRef("pk"))                          
        .distinct('date__date')                                                  
        .annotate(count=Count('pk'))                                             
        .values('count')                                                         
    )                                                                            
)

I tried to reference this solutionan earlier post solved by Willem 结合使用,但使用 distinct 似乎会导致上面提到的 NotImplementedError。我相信也可能有一个使用 Count( , distinct=True) 的解决方案,但除非我可以在 date__date 上区分,否则它无济于事,因为我只是想找出发生了任意数量的交易的日期。

非常感谢您的宝贵时间。

【问题讨论】:

    标签: django subquery distinct primary-key django-annotate


    【解决方案1】:

    解决方案 1(使用外键)

    RetailLocation.objects.annotate(days_operating=Count('transaction__date__date', distinct=True))
    

    利用RetailLocation和Transaction的ForeignKey关系,首先按照ForeignKey获取Transaction对象的相关集合('transaction'),然后选择'date'列('transaction_date'),最后将其转换为日期('transaction_date_date')。这将返回一个字典列表 {date_date: date objects},并使用 Count( , distinct=True) 计算唯一日期集。

    解决方案 2(使用子查询)

    test = RetailLocation.objects.annotate(                                                    
        days_operating=Subquery(                                                     
        Transaction.objects.filter(r_loc=OuterRef("pk"))
        .values('r_loc')
        .annotate(count=Count('date__date', distinct=True))                                             
        .values('count')
        )
    )
                                                                          
    

    这与解决方案 1 的工作方式基本相同,但如果您想根据其他内容(可能是日期)进行过滤,则不需要需要在两个模型之间建立 ForeignKey 关系。

    Useful link on Subquery Aggregation

    【讨论】:

      猜你喜欢
      • 2016-11-29
      • 1970-01-01
      • 2018-07-01
      • 1970-01-01
      • 2011-11-04
      • 1970-01-01
      • 2010-11-23
      • 2015-08-24
      • 2013-06-03
      相关资源
      最近更新 更多