O requisito de chave primária no SQL bruto complica a consulta no Django

Para obter o valor máximo de uma tabela de valores simples, eu posso escrever a seguinte consulta no Django:

MyTable.objects.aggregate(Max('value'))

O SQL gerado é:'SELECT MAX("mytable"."value") AS "value__max" FROM "mytable"'

Agora, se eu escrever o mesmo SQL usando o gerenciador de consultas brutas:

1. MyTable.objects.raw('SELECT max(value) FROM mytable')

Django lança um erroInvalidQuery: Raw query must include the primary key. Isso também é mencionado nos documentos do Django: "Há apenas um campo que você não pode deixar de fora - o campo da chave primária". Então, depois de adicionar oid campo precisoGROUP BY também. A nova consulta se torna:

2. MyTable.objects.raw('SELECT id, max(value) FROM mytable GROUP BY id')

Isso não me dá mais um único valor máximo porque sou forçado a usarGROUP BY id. Agora preciso adicionar umORDER BY eLIMIT para obter a resposta esperada para uma instrução SQL simples que funcione.

3. MyTable.objects.raw('SELECT id, max(value) AS mv FROM mytable GROUP BY id ORDER BY mv DESC LIMIT 1')

Existe uma maneira de simplificar a consulta acima, ou seja, não usar ORDER / LIMIT / GROUP BY (FWIW, usando PosgreSQL)?

Atualizar:

Aqui está um truque que funcionará. Eu alias o valor máximo comoid para fazer o Django feliz. Existe algum problema aqui?

MyTable.objects.raw('SELECT max(value) AS id FROM mytable')

Atualização 2:

Aqui está o plano de consulta para o SQL simples (1) e o final complicado (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. A consulta real é mais complicada (um pouco relacionada a esta resposta:https://dba.stackexchange.com/a/86404/52114)

questionAnswers(3)

yourAnswerToTheQuestion