为了从简单的值表中获取最大值,我可以在Django中编写以下查询:
MyTable.objects.aggregate(Max('value'))
生成的SQL是: 'SELECT MAX("mytable"."value") AS "value__max" FROM "mytable"'
'SELECT MAX("mytable"."value") AS "value__max" FROM "mytable"'
现在,如果我使用原始查询管理器编写相同的SQL:
1. MyTable.objects.raw('SELECT max(value) FROM mytable')
Django抛出错误InvalidQuery: Raw query must include the primary key。Django docs中也提到了这一点:“您只能忽略一个字段-主键字段”。因此,添加id字段后,我也需要GROUP BY。新查询变为:
InvalidQuery: Raw query must include the primary key
id
GROUP BY
2. MyTable.objects.raw('SELECT id, max(value) FROM mytable GROUP BY id')
这不再给我一个最大值,因为我被迫使用GROUP BY id。现在,我需要添加ORDER BYandLIMIT语句,以获取可以正常工作的否则简单的SQL语句的预期答案。
GROUP BY id
ORDER BY
LIMIT
3. MyTable.objects.raw('SELECT id, max(value) AS mv FROM mytable GROUP BY id ORDER BY mv DESC LIMIT 1')
有没有一种方法可以简化上述查询,即不使用ORDER / LIMIT / GROUP BY(FWIW,使用PosgreSQL)?
更新:
这是一种可行的技巧。我将最大值设为别名,id以使Django满意。这里有什么问题吗?
MyTable.objects.raw('SELECT max(value) AS id FROM mytable')
更新2:
这是简单的SQL(1)与复杂的最后一个(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"
您应该使用自定义SQL而不是Manager.raw()方法:
Manager.raw()
from django.db import connection cursor = connection.cursor() cursor.execute('SELECT max(value) FROM mytable') max_value = cursor.fetchone()[0]