Myślę, że najlepiej będzie to wyjaśnić na przykładzie.Czy mogę kontrolować GROUP BY w aplikacji django 1.3?
Oto jakie dane będzie wygląda następująco:
|project |
|id|name |
|1 |some project |
|2 |my other project|
|run |
|id|project_id|start_time |result |
|1 |1 |1305732581845|something|
|2 |1 |1305732593721|nothing |
|3 |2 |1305732343721|nothing |
|4 |2 |1305732556821|something|
Chciałbym być w stanie uzyskać cały zestaw rekordów z każdego z najnowszymi biegnie przez projekt. Zapytania SQL będzie wyglądać mniej więcej tak:
SELECT *, MAX("run"."start_time")
FROM "run"
LEFT OUTER JOIN "project" ON ("run"."project_id" = "project"."id")
GROUP BY "project"."id"
ten powróci mi wszystkie kolumny w obu tabelach do najnowszej przebiegu projektu, co jest dobre, to jest dokładnie to, czego potrzebuję.
Tak więc, próbując znaleźć ekwiwalent django w django 1.3, po prostu nie mogę znaleźć odpowiedniego sposobu na zrobienie tego. Jeśli robię coś takiego:
Run.objects.annotate(Max('start_time'))
Wygenerowany zapytań SQL będzie wyglądać mniej więcej tak:
SELECT
"run"."id", "run"."result", "run"."project_id", "project"."id", "project"."name",
MAX("run"."start_time")
FROM "run"
LEFT OUTER JOIN "project" ON ("run"."project_id" = "project"."id")
GROUP BY "run"."id", "run"."result", "run"."project_id", "project"."id", "project"."name"
To nie wróci mi odpowiednie wyniki grupy przez jest niepoprawna dla czego chcę. Wierzę w poprzednich wersjach Django przyszły poprawnie i wyraźnie określone grupy przez klauzuli w zapytaniu następujących ale wydaje się nie działać w 1.3:
q = Run.objects.annotate(Max('start_time'))
q.query.group_by = [("project", "id")]
w 1.3 to generuje dokładnie to samo zapytanie, jak nie ręcznie modyfikując group_by właściwość w zapytaniu.
Próbowałem również logicznie w oparciu o udokumentowane zachowanie .values () przed i po wywołaniu adnotate(), ale nie działało ono zgodnie z oczekiwaniami. Kiedy próbowałem to:
q = Run.objects.values('project__id').annotate(Max('start_time')).values('id')
skończyło się z zapytaniem jak to:
SELECT
"run"."id", "run"."project_id"
MAX("run"."start_time")
FROM "run"
LEFT OUTER JOIN "project" ON ("run"."project_id" = "project"."id")
GROUP BY "run"."id", "run"."project_id"
Czy ktoś może wskazać mi właściwy sposób, aby robić to, co robię, bez żadnej z następujących czynności:
- Używanie surowego sql - jaki byłby sens używania orm, gdy ciągle muszę generować własne zapytania?
- Korzystanie z .extra (select = {'latest': 'somequery'}) - dlaczego powinienem używać podkwerend, gdy idealnie poprawne zapytanie bez podzapytań może dać mi to, czego chcę.
- Używanie wielu zapytań do przechwytywania tych samych danych - jeszcze raz, dlaczego powinienem wykonać wiele zapytań, aby uzyskać wyniki dostępne w 1?
To nie zwróci całego zestawu rekordów dla każdego wiersza. Poda mi tylko wartości z kolumn na liście wartości. Oznacza to, że nie mogę uzyskać danych z kolumn bez grupowania według kolumn i niestety potrzebuję identyfikatorów przebiegu. – mockobject
'wartości (" zgrupowania, ...). Adnotate(). Wartości ("more_fields_to_show_here") Upewnij się, że dodajesz nazwę pola dodanego przez adnotację do wartości term po adnotacji Naprawdę powinieneś przeczytać https://docs.djangoproject.com/en/1.3/topics/db/aggregation/#order-of-annotate-and-values-clauses – John
Zapomniałem wspomnieć, że była to pierwsza metoda, którą wypróbowałem, ponieważ na podstawie dokumentacji wydawało się to logiczną drogą. Nie zadziałało jednak zgodnie z oczekiwaniami. Wszystkie wartości w tych ostatnich wartościach kończą się w klauzuli group_by. Czytałem dokumentację, która po prostu nie działa zgodnie z oczekiwaniami, chyba że robię z nią coś bardzo nie tak. Zaktualizuję oryginalne pytanie, aby zauważyć, że próbowałem tego i jakie były wyniki, było to tylko niedopatrzenie, gdy pisałem to pytanie. – mockobject