7

モデル XYZ があり、特定のクエリセットのフィールド a、b、および式 x/y の最大値を取得する必要があります。

それはフィールドのために美しく機能します。何かのようなもの:

>>> XYZ.all().aggregate(Max('a'))

... {'a__max': 10}

しかし、式に対してそれを行う方法が見つかりません。次のようなものを試してください:

>>> XYZ.all().aggregate(Max('x/y'))

エラーが発生します:

*** FieldError: Cannot resolve keyword 'x/y' into field. Choices are: a, b, x, y, id

次のようなものを試してください:

>>> XYZ.all().aggregate(Max(F('x')/F('y')))

エラーが発生します:

*** AttributeError: 'ExpressionNode' object has no attribute 'split'

そして、次のようなものさえ:

XYZ.all().extra(select={'z':'x/y'}).aggregate(Max('z'))

また、機能せず、上記と同じエラーが発生します。

FieldError: Cannot resolve keyword 'z' into field. Choices are: a, b, x, y, id

私が見つけた1つのハックは次のとおりです。

XYZ.all().extra(select={'z':'MAX(x/y)'})[0].z

これは正しい SQL を生成するため実際に機能しますが、z 属性で正しい値を取得するため、混乱を招きますが、その最大値を持つインスタンスは正しくありません。

もちろん、extra() と order_by() で生のクエリやトリックを使用することもできますが、Django が集約クエリをうまくサポートしているのにサポートできないというのは、私にはまったく意味がありません。独自の F 式を含む式。

それを行う方法はありますか?

4

4 に答える 4

6

SQLでは、実際に欲しいのは

SELECT x/y, * FROM XYZ ORDER BY x/y DESC LIMIT 1;
# Or more verbose version of the #1
SELECT x/y, id, a, b, x, y FROM XYZ GROUP BY x/y, id, a, b, x, y ORDER BY x/y DESC LIMIT 1;
# Or
SELECT * FROM XYZ WHERE x/y = (SELECT MAX(x/y) FROM XYZ) LIMIT 1;

したがって、Django ORM では次のようになります。

XYZ.objects.extra(select={'z':'x/y'}).order_by('-z')[0]
# Or
XYZ.objects.extra(select={'z':'x/y'}).annotate().order_by('-z')[0]
# Or x/y=z => x=y*z
XYZ.objects.filter(x=models.F('y') * XYZ.objects.extra(select={'z':'MAX(x/y)'})[0].z)[0]

バージョン

XYZ.all().extra(select={'z':'MAX(x/y)'})[0].z

MAXが存在しない場合、関数はすべての行で評価されるため、 は正しい x、y およびインスタンスを持ちませんGROUP BY。したがって、返される QuerySet 内のすべてのインスタンスは、zasと同じ値になりMAX(x/y)ます。

于 2012-04-19T14:31:02.460 に答える
3

F()Django 1.8以降、オブジェクトを使用する例は正常に機能するはずです:

XYZ.all().aggregate(Max(F('x')/F('y')))

Django 集計チート シートSum()には、F()オブジェクトを使用した集計を示すスニペットがあります。

Book.objects.all().aggregate(price_per_page=Sum(F('price')/F('pages'))
于 2016-01-05T23:00:27.103 に答える
0

1.8 より前のバージョンでは、この (文書化されていない) 方法で同じことを実現できます。

Book.objects.all().aggregate(price_per_page=Sum('price_per_page', 
                                                field='book_price/book_pages'))

これはPostgresで機能しますが、MySQLについては知りません。

ソース: Django 集計: 2 つのフィールドの乗算の合計

于 2016-06-03T14:04:16.270 に答える
-3

最大値を個別に取得する必要があると思います

result = XYZ.aggregate(Max('x'), Max('y'))

そして、2つのフィールドを分割します

result['x__max'] \ result['y__max']
于 2012-04-19T05:30:24.923 に答える