1

使用子查询进入深水区。我有一套Carparks。Carparks 有多个Bookings。Bookings有很多BarrierActivity记录,就是关口的各种来来去去的事件。这些都是堆栈中的简单 FK。

预订可能会到达,但屏障摄像头无法识别它。一名工作人员会给他们打电话,但这意味着系统由于某种原因失败了。这就是我在这里想要做的。算出我的预订中有多少是通过自动方式获得的。我知道还有很多其他方法可以做到这一点,但我想用一个基于子查询的查询集来做到这一点。

我的目标相当简单。BarrierActivity注释 0 或 1 以显示每个是否存在“条目” Booking。注释这些值的平均值,每Carpark

第一部分很好。我可以在和之间做一个简单的Exists(),然后每个预订都有 0 或 1:BarrierActivityBooking

successful_bas = BarrierActivity.objects.order_by().filter(
    booking=OuterRef('pk'),
    activity_type=BarrierActivity.TYPE_ANPR_BOOKING,
    direction='entry'
).values('booking')

Booking.objects.order_by().annotate(
    entry_success=Exists(successful_bas)
)

再一次,这很好用。但是一旦我尝试扩大另一层(所以看Carpark而不是Booking)......

successful_bas = BarrierActivity.objects.order_by().filter(
    booking=OuterRef('pk'),
    activity_type=BarrierActivity.TYPE_ANPR_BOOKING,
    direction='entry'
).values('booking')

bookings = Booking.objects.order_by().filter(
    carpark=OuterRef('pk')
).values('carpark').annotate(
    entry_success=Exists(successful_bas)
).values('entry_success')

Carpark.objects.order_by().annotate(
    entry_hitrate=ExpressionWrapper(
        Avg(Cast(Subquery(bookings), IntegerField())) * 100,
        output_field=FloatField()
    )
)

...我得到了 Subquery-error-of-doom: more than one row returned by a subquery used as an expressionbookings子查询显然返回了太多,但我如何在它到达最外层子查询之前聚合它?


我已经尝试了很多事情,但是这里将平均值重新组织到子查询中。同样的错误:

successful_bas = "... as before ..."

bookings = Booking.objects_standard.order_by().filter(
    carpark=OuterRef('pk')
).values('site').annotate(
    entry_success=Exists(successful_bas)
).annotate(
    entry_avg=Avg(Cast('entry_success', IntegerField()))
).values('entry_avg')

Carpark.objects.order_by().annotate(
    entry_hitrate=ExpressionWrapper(
        Subquery(bookings, output_field=FloatField()) * 100,
        output_field=FloatField()
    )
)
4

1 回答 1

0

我能够在我自己的一个项目中重新创建其中的一部分,并将 a 添加distinct('<values_field_name>').order_by()到外部子查询中解决了它。

需要 distinct 调用来减少返回的行数。不同调用中的字段名称是必需的,否则它会尝试跨另一个字段进行不同调用。然后order_by()调用清除任何排序,以便查询具有与初始表达式排序匹配的不同表达式的排序。

这就是我要尝试的:

successful_bas = BarrierActivity.objects.order_by().filter(
    booking=OuterRef('pk'),
    activity_type=BarrierActivity.TYPE_ANPR_BOOKING,
    direction='entry'
).values('booking')

bookings = Booking.objects.order_by().filter(
    carpark=OuterRef('pk')
).annotate(
    entry_success=Exists(successful_bas)
).values('carpark').distinct('carpark').order_by()

Carpark.objects.order_by().annotate(
    entry_hitrate=ExpressionWrapper(
        Avg(Cast(Subquery(bookings), IntegerField())) * 100,
        output_field=FloatField()
    )
)

请注意,我删除values了外部子查询中的一个调用。

于 2017-06-07T18:10:20.410 回答