サブクエリで深い水に入る。私はCarpark
のセットを持っています。 Carpark
に複数のBooking
があります。予約には、障壁での様々な行き来するイベントである多くのBarrierActivity
レコードがあります。これらはすべてスタック上の単純なFKです。Djangoのネストされたサブクエリ
予約は到着することができ、バリアカメラはではありません。スタッフの一員がそれを鳴らしますが、それは何らかの理由でシステムが失敗したことを意味します。それが私がここでやろうとしていることです。私の予約の何パーセントが自動化された手段で取り込まれたかを調べる。私はこれを行う他の多くの方法があることを知っていますが、私は単一のサブクエリベースのクエリセットでこれをやりたいと思います。
私の目的はかなり簡単です。各Booking
に「エントリ」BarrierActivity
が存在するかどうかを示す0または1の注釈を付けます。これらの値の平均値をCarpark
に注記してください。
最初の部分は問題ありません。私はBarrierActivity
とBooking
間の単純なExists()
を行うことができますし、各予約が0または1を持っています
そして再び、正常に動作しています。しかし、すぐに、私は別の層(そう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()
)
)
ていることにスケールアップしようとして...私はサブクエリ誤りの-運命を得る:more than one row returned by a subquery used as an expression
。 bookings
サブクエリーは明らかにあまりにも多くを返しますが、最も外側のサブクエリに当たる前にそれをどのように集計しますか?
私は多くのことを試しましたが、ここではサブクエリ内の平均値を再編成しています。同じエラー:
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()
)
)
サブクエリが複数返されています。キャストを呼び出す前に平均を取る – Brobin
キャストはAvgが動作するために必要です(bool→intを実行しています)。私はいくつかの選択肢を試してみました - 良い効果はありません - あなたが提案しているもののように編集します。 – Oli
@Oliあなたのアプローチが不必要に複雑すぎるように見える(boolをintにキャストしてから平均していくのか?)、単純なアプローチで簡単なアプローチを見つけることができます。 – Todor