Primärschlüsselanforderung in Raw SQL erschwert die Abfrage in Django
Um den maximalen Wert aus einer einfachen Wertetabelle zu erhalten, kann ich die folgende Abfrage in Django schreiben:
MyTable.objects.aggregate(Max('value'))
Die generierte SQL ist:'SELECT MAX("mytable"."value") AS "value__max" FROM "mytable"'
Nun, wenn ich dieselbe SQL mit dem Raw-Abfrage-Manager schreibe:
1. MyTable.objects.raw('SELECT max(value) FROM mytable')
Django wirft einen FehlerInvalidQuery: Raw query must include the primary key
. Dies wird auch in Django-Dokumenten erwähnt: "Es gibt nur ein Feld, das Sie nicht auslassen dürfen - das Primärschlüsselfeld". Also nach dem Hinzufügen desid
field, ich braucheGROUP BY
auch. Die neue Abfrage lautet:
2. MyTable.objects.raw('SELECT id, max(value) FROM mytable GROUP BY id')
Dies gibt mir keinen einzigen Maximalwert mehr, weil ich gezwungen bin, @ zu verwendeGROUP BY id
. Jetzt muss ich ein @ hinzufügORDER BY
undLIMIT
Anweisung, um die erwartete Antwort für eine ansonsten einfache SQL-Anweisung zu erhalten, die funktioniert.
3. MyTable.objects.raw('SELECT id, max(value) AS mv FROM mytable GROUP BY id ORDER BY mv DESC LIMIT 1')
Gibt es eine Möglichkeit, die obige Abfrage zu vereinfachen, d. H. ORDER / LIMIT / GROUP BY (FWIW, PosgreSQL) nicht zu verwenden?
Aktualisieren
Hier ist ein Hack, der funktionieren wird. Ich alias der Maximalwert alsid
um Django glücklich zu machen. Gibt es hier ein Problem?
MyTable.objects.raw('SELECT max(value) AS id FROM mytable')
Update 2:
Hier ist der Abfrageplan für das einfache SQL (1) im Vergleich zum komplizierten endgültigen SQL (3):
"Aggregate (cost=5.25..5.26 rows=1 width=2) (actual time=0.155..0.155 rows=1 loops=1)"
" -> Seq Scan on mytable (cost=0.00..4.60 rows=260 width=2) (actual time=0.018..0.067 rows=260 loops=1)"
"Total runtime: 0.222 ms"
"Limit (cost=9.80..9.80 rows=1 width=6) (actual time=0.548..0.548 rows=1 loops=1)"
" -> Sort (cost=9.80..10.45 rows=260 width=6) (actual time=0.545..0.545 rows=1 loops=1)"
" Sort Key: (max(value))"
" Sort Method: top-N heapsort Memory: 25kB"
" -> HashAggregate (cost=5.90..8.50 rows=260 width=6) (actual time=0.328..0.432 rows=260 loops=1)"
" -> Seq Scan on mytable (cost=0.00..4.60 rows=260 width=6) (actual time=0.018..0.069 rows=260 loops=1)"
"Total runtime: 0.638 ms"
P.S. Die eigentliche Abfrage ist komplizierter (etwas im Zusammenhang mit dieser Antwort:https: //dba.stackexchange.com/a/86404/5211)