DjangoでSELECTMAXを実行するにはどうすればよいですか?


91

オブジェクトのリストがあります。クエリを実行してフィールドの最大値を指定するにはどうすればよいですか。

私はこのコードを使用しています:

def get_best_argument(self):
    try:
        arg = self.argument_set.order_by('-rating')[0].details
    except IndexError:
        return 'no posts'
    return arg

評価は整数です

回答:


172

これを参照してください。コードは次のようになります。

from django.db.models import Max
# Generates a "SELECT MAX..." query
Argument.objects.aggregate(Max('rating')) # {'rating__max': 5}

これは、既存のクエリセットでも使用できます。

from django.db.models import Max
args = Argument.objects.filter(name='foo') # or whatever arbitrary queryset
args.aggregate(Max('rating')) # {'rating__max': 5}

この最大値を含むモデルインスタンスが必要な場合は、投稿したコードがおそらくそれを行うための最良の方法です。

arg = args.order_by('-rating')[0]

クエリセットが空の場合、つまりクエリに一致する引数がない場合、これはエラーになることに注意してください([0]パーツがを発生させるためIndexError)。その動作を回避し、代わりNoneにその場合に戻る場合は、次を使用します.first()

arg = args.order_by('-rating').first() # may return None

4
そのMaxを持つactuall引数オブジェクトが必要なので、詳細フィールドを出力できます。args.aggregate(Max( 'rating'))呼び出しは、最高の評価を返すだけです。最高の評価の引数を探しています。
ジョンド2009年

1
既存のコードの何が問題になっていますか-Argument.objects.order_by( "-rating")[0]?
AdamKG 2009年

73

Djangoには、最新の(最大値)エントリを検索する ' latest(field_name = None) '関数もあります。日付フィールドだけでなく、文字列や整数でも機能します。

その関数を呼び出すときに、フィールド名を指定できます。

max_rated_entry = YourModel.objects.latest('rating')
return max_rated_entry.details

または、モデルのメタデータでそのフィールド名をすでに指定することもできます。

from django.db import models

class YourModel(models.Model):
    #your class definition
    class Meta:
        get_latest_by = 'rating'

これで、パラメータなしで 'latest()'を呼び出すことができます。

max_rated_entry = YourModel.objects.latest()
return max_rated_entry.details

3
これは、を使用するのに最適な方法ですlatest()。最小値のレコードが必要な場合は、を使用できますearliest()
SaeX 2016年

7
latest()そしてearliest()、あまりにも非日付フィールドで動作しますが、それは実装の副作用です。Django開発者が変更し、実装が日付フィールドのみで機能するようになった場合でも、<your-queryset>.order_by('<interested-field>').first()または<your-queryset>.order_by('<interested-field>').last()を使用してコードが機能することを確認する必要があります。latest()earliest()
mrnfrancesco 2017

これは悪い答えです:1)すでに気づいたように、実装の詳細であり、将来変更される可能性があります2)あまり読みにくい-最大数は必ずしも最新のものではありません(または他の意味で)
Mikhail Gerasimov

47

私は自分のプロジェクトでこれをテストしました、それはO(n)時間で最大/最小を見つけます:

from django.db.models import Max

# Find the maximum value of the rating and then get the record with that rating. 
# Notice the double underscores in rating__max
max_rating = App.objects.aggregate(Max('rating'))['rating__max']
return App.objects.get(rating=max_rating)

これにより、テーブル全体を並べ替えて最上位(O(n * logn)付近)を取得するのではなく、最大要素の1つを効率的に取得できることが保証されます。


8
Big-Oは、特に係数と実装が重要な小さいnの場合、実際にはうまくいかないことがあります。コードはpython / djangoにあり、バイトコードにコンパイルされており、最適化されている場合とされていない場合があります。データベースは、機械命令に最適化およびコンパイルされた言語で記述されている可能性があります。さらに、関数が最大値のみを検索している場合、データベースにはソートする本当の理由がありません。組み込みのデータベース関数でハンドビルドコードを使用する前に、タイミングデータを確認したいと思います。
benevolentprof 2013

5
@afahimこれはあなたが投稿したコードが完全に正しいとは思いません。最大値が複数あることが判明した場合(たとえば、5つ星のアプリが2つある場合)、「get」を使用するとエラーが発生します。
レイデルミランダ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.