Django注释复杂的子查询计数

时间:2019-11-01 18:08:21

标签: django django-orm django-annotate django-subquery

我有以下模型:

class Visit(models.Model):
   ...
   device_id = models.CharField(...)
   created_at = models.DateTimeField(auto_now_add=True)
   ...

此模型基本上表示对一个地方的访问,device_id唯一地标识一个人,并且同一个人可以多次访问该地方,因此在此表中创建了多个实体。

我正在此模型之上构建分析方法。我想做的一件事是,在过去30天中,显示当天仅拜访过一次的人数。通过一种基本方法,我可以每天这样发出数据库查询:

for date in dates:
    start_time = date
    end_time = date + datetime.timedelta(days=1)

    Visitor.objects.filter(
        site__in=node_descendants,
        created_at__gte=start_date,
        created_at__lt=end_date)
    ).values('device_id').annotate(visit_count=Count('device_id')).filter(visit_count=1).count()

现在,我想使用像这样的子查询通过一个查询来计算30天范围内每一天的数据:

single_visitor_query = Visitor.objects.filter(
    created_at__date=OuterRef('truncated_date')
).order_by().values('device_id')
 .annotate(visit_count=Count('device_id')).filter(visit_count=1)
 .annotate(count=Count('*')).values('count')

chart_data_query = Visitor.objects.filter(
    created_at__gte=start_date,  # Start of month
    created_at__lt=end_date,  # End of month
).annotate(
    truncated_date=TruncDay('created_at')
).values('truncated_date').distinct().annotate(
    single_visitor_count=Subquery(single_visitor_query[:1], output_field=PositiveIntegerField()
)

这种方法有很多问题:

    子查询产生的
  • count并不是具有visit_count = 1的所有项目的计数,而是全部为1。我知道该子查询有些不正确,但是我看不到如何解决该问题以返回所有计数通过过滤器的项目。
  • 我希望子查询针对每个truncated_date(在这种情况下为30次)运行,但似乎它对每个通过初始筛选器的实例都运行。我检查了生成的sql查询,它没有按“ 截断日期”进行分组。为什么会有这种想法?

0 个答案:

没有答案
相关问题