/ / Django: jak filtrować () po distinct () - django

Django: jak filtrować () po distinct () - django

Jeśli wywołamy połączenie z filtrem () po wywołaniu funkcji distinct (), filtr zostanie zastosowany do zapytania przed odróżnieniem. Jak filtrować wyniki zapytania po stosować różne?

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

Klauzula where w SQL wynikająca z filter () oznacza, że ​​filtr jest stosowany do zapytania przed odróżnieniem. Chcę filtrować zestaw zapytań wynikających z odrębnego.

Jest to prawdopodobnie dość łatwe, ale po prostu nie mogę tego zrozumieć i nie mogę znaleźć niczego na ten temat.

Edytuj 1:

Muszę to zrobić w 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";

(Używam PostgreS nawiasem mówiąc.) Domyślam się, że pytam: "Jak zagnieżdżać podzapytania w ORM? Czy to możliwe?" Sprawdzę dokumentację.

Przepraszam, jeśli nie byłam specyficzna wcześniej. To nie było jasne w mojej głowie.

Odpowiedzi:

2 dla odpowiedzi № 1

Jest to stare pytanie, ale podczas korzystania z Postgres możesz wykonać następujące czynności, aby wymusić zapytanie zagnieżdżone w "Wyróżnionych" wierszach:

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

pasek jest zapytaniem zagnieżdżonym, zgodnie z wnioskiem w OP, bez stosowania surowych / dodatkowych itp. Testowany działa w wersji 1.10, ale dokumenty sugerują, że powinien powrócić do co najmniej 1,7.

Moim przypadkiem użycia było filtrowanie odwrotnej relacji. Jeśli w przykładzie jest jakiś klucz obcy do modelu Toast, możesz zrobić:

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

To daje wszystkie instancje Toast, gdzie ostatni skojarzony przykład spełnia kryteria filtru.

Duże zagrożenie dla zdrowia dotyczące wydajności, używając tego, jeśli pasek jest prawdopodobnie dużym zestawem zapytań, prawdopodobnie "będzie źle".


1 dla odpowiedzi nr 2

Nie, nie możesz tego zrobić w jednym prostym WYBIERZ.
Jak powiedziałeś w komentarzach, w Django ORM filter jest zamapowany na klauzulę SQL WHERE, i distinct zmapowany do DISTINCT. I w SQL, DISTINCT zawsze dzieje się po WHERE operując na zestawie wyników, patrz Dokument SQLite na przykład.

Ale możesz napisać pod-zapytanie, aby zagnieździć SELEKTY, to zależy od rzeczywistego celu (nie wiem dokładnie, co teraz twoja. Czy mógłbyś go bardziej rozwinąć?)

Ponadto w przypadku zapytania distinct("a") utrzymuje tylko pierwsze wystąpienie Example mając to samo a, czy tego chcesz?


1 dla odpowiedzi nr 3

Dzięki za pomoc dla facetów. Próbowałem obu sugestii i nie mogłem zgiąć żadnej z tych sugestii do działania, ale myślę, że zaczęło to we właściwym kierunku.

Skończyło się na użyciu

from django.db.models import Max, F

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

To sprawdza, co najnowszego foreignkey__timefieldjest dla każdego przykładu, a jeśli jest ostatni i a = coś, to zachowaj go. Jeśli nie jest to najnowszy lub a! = Coś dla każdego przykładu, to zostanie odfiltrowane.

Nie zagnieżdża podzapytań, ale daje mi wynik, którego szukam - i jest dość prosty. Jeśli jest prostszy sposób, naprawdę chciałbym to wiedzieć.