/ / Django:distinct()の後にどのように()をフィルタリングするか - django

Django:フィルターをかける方法()distinct()の後 - django

distinct()への呼び出しの後にfilter()への呼び出しをチェーニングすると、フィルターはdistinctの前のクエリに適用されます。クエリの結果をフィルタする方法 異なる適用?

Example.objects.order_by("a","foreignkey__b").distinct("a").filter(foreignkey__b="something")

filter()の結果として生じるSQLのwhere句は、フィルタがdistinctの前にクエリに適用されることを意味します。 distinctから得られたクエリセットをフィルタリングしたいです。

これはおそらく非常に簡単ですが、私はそれを理解することができず、何も見つけることができません。

編集1:

私はこれをORMで行う必要があります...

SELECT z.column1, z.column2, z.column3 FROM ( SELECT DISTINCT ON (b.column1, b.column2) b.column1, b.column2, c.column3 FROM table1 a INNER JOIN table2 b ON ( a.id = b.id ) INNER JOIN table3 c ON ( b.id = c.id) ORDER BY b.column1 ASC, b.column2 ASC, c.column4 DESC ) z WHERE z.column3 = "Something";

(私はところでPostgresを使っています。) だから私は私が求めているのは「ORMにサブクエリをどのようにネストするのですか?可能ですか?」と思います。ドキュメントを確認します。

私が先に特定されていない場合は申し訳ありません。頭がよくわからなかった。

回答:

回答№1は2

これは昔からの質問ですが、Postgresを使用しているときに "Distinct"行にネストしたクエリを強制するには、次のようにします。

foo = Example.objects.order_by("a","foreign_key__timefield").distinct("a")
bar = Example.objects.filter(pk__in=foo).filter(some_field=condition)

barは、raw / extraなどに頼ることなく、OPで要求されているようなネストされたクエリです。1.10での動作をテストしましたが、ドキュメントによれば、少なくとも1.7に戻ります。

私のユースケースは逆の関係をフィルタリングすることでした。 ExampleにToastをモデル化するためのForeignKeyがある場合は、次の操作を実行できます。

Toast.objects.filter(pk__in=bar.values_list("foreign_key",flat=true))

これにより、関連する最新の例がフィルタ基準を満たすToastのすべてのインスタンスが得られます。

ただし、パフォーマンスに関する大きな健康警告が表示されます。バーを使用するのは巨大なクエリセットになる可能性が高いため、「悪い時間を過ごすことになるでしょう。


回答№2の場合は1

いいえ、これを1つの単純なSELECTで行うことはできません。
コメントで述べたように、Django ORMで filter SQL文節にマップされている WHERE、および distinct マップされた DISTINCT。そしてSQLでは、 DISTINCT 常に後に起こる WHERE 結果セットを操作して、を見てください。 SQLiteのドキュメント 例えば。

しかし、SELECTをネストするサブクエリを書くこともできます。これは実際のターゲットによって異なります(現在自分のものが何であるか正確にはわからない。もっと詳しく説明してもらえますか?)

また、あなたの質問のために、 distinct("a") の最初の出現のみを保持します Example 同じこと a、それがあなたが欲しいものですか?


回答№3の場合は1

助けてくれてありがとう。私は両方の提案を試してみましたが、どちらの提案もうまく動くように曲げることはできませんでしたが、私は正しい方向に向かったと思います。

私は使用を終了した

from django.db.models import Max, F

Example.objects.annotate(latest=Max("foreignkey__timefield")).filter(foreignkey__timefield=F("latest"), foreign__a="Something")

これは最新のforeignkey__timefieldをチェックします。これは各例に対するものであり、それが最新のものでありかつa =何かであるならば、それを保持してください。それが各実施例にとって最新でないか、または!=何かではない場合、それは除外される。

これはサブクエリを入れ子にすることではありませんが、探している結果を得ることができます - そしてそれはかなり簡単です。もっと簡単な方法があれば、私は本当に知りたいと思います。