/ / Django: wie man filter () nach distinct () - django

Django: wie man filter () nach distinct () - django

Wenn wir einen Aufruf von filter () nach einem Aufruf von distinct () verketten, wird der Filter auf die Abfrage vor dem distinct angewendet. Wie filtere ich die Ergebnisse einer Abfrage? nach anders anwenden?

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

Die von filter () resultierende where-Klausel in der SQL-Anweisung bedeutet, dass der Filter auf die Abfrage vor dem distinct angewendet wird. Ich möchte das queryset filtern, das vom distinct resultiert.

Das ist wahrscheinlich ziemlich einfach, aber ich kann es mir nicht vorstellen und ich kann nichts finden.

Bearbeiten 1:

Ich muss das im ORM machen ...

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";

(Ich benutze übrigens Postgres.) Also ich denke, was ich frage ist "Wie verschachteln Sie Unterabfragen im ORM? Ist es möglich?" Ich werde die Dokumentation überprüfen.

Entschuldigung, wenn ich vorher nicht ausdrücklich war. Es war nicht klar in meinem Kopf.

Antworten:

2 für die Antwort № 1

Dies ist eine alte Frage, aber wenn Sie Postgres verwenden, können Sie Folgendes tun, um verschachtelte Abfragen in Ihren "Distinct" -Zeilen zu erzwingen:

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

bar ist die verschachtelte Abfrage, wie in OP angefordert, ohne auf rohe / zusätzliche Daten zurückgreifen zu müssen. Getestet in 1.10, aber die Dokumentation schlägt vor, dass sie auf mindestens 1.7 zurückgehen sollte.

Mein Anwendungsfall war es, eine umgekehrte Beziehung zu filtern. Wenn Example einen ForeignKey zum Modellieren von Toast hat, können Sie Folgendes tun:

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

Dadurch erhalten Sie alle Instanzen von Toast, bei denen das zuletzt zugeordnete Beispiel Ihren Filterkriterien entspricht.

Allerdings gibt es eine große Warnmeldung zur Performance. Wenn Sie diese Option verwenden, wird es wahrscheinlich eine große Anfrage sein, dass Sie wahrscheinlich eine schlechte Zeit haben werden.


1 für die Antwort № 2

Nein, das kann man nicht in einem einfachen SELECT tun.
Wie Sie in den Kommentaren in Django ORM gesagt haben filter ist der SQL-Klausel zugeordnet WHERE, und distinct zugeordnet zu DISTINCT. Und in einem SQL, DISTINCT passiert immer danach WHERE durch Arbeiten am Ergebnissatz, siehe SQLite-Dokument beispielsweise.

Aber Sie könnten eine Unterabfrage schreiben, um SELECTs zu verschachteln, das hängt vom tatsächlichen Ziel ab (ich weiß nicht genau, was Sie jetzt haben ... könnten Sie es genauer ausarbeiten?)

Auch für Ihre Anfrage, distinct("a") hält nur das erste Vorkommen von Example das selbe haben a, ist es das was du willst?


1 für die Antwort № 3

Vielen Dank für die Hilfe Jungs. Ich habe beide Vorschläge ausprobiert und konnte keinen dieser Vorschläge zur Ausführung bringen, aber ich denke, es hat mich in die richtige Richtung gebracht.

Ich habe es benutzt

from django.db.models import Max, F

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

Dies überprüft, was das neueste Fremdschlüssel-__-Zeitfeld istist für jedes Beispiel, und wenn es das neueste ist und a = etwas dann behalte es. Wenn es für jedes Beispiel nicht das letzte oder ein! = Etwas ist, wird es herausgefiltert.

Dies verschachtelt keine Unterabfragen, aber es gibt mir die Ausgabe, die ich suche - und es ist ziemlich einfach. Wenn es einen einfacheren Weg gäbe, würde ich es gerne wissen.