当前位置: 首页 > 面试题库 >

原始SQL中的主键要求使Django中的查询复杂化

冉子石
2023-03-14
问题内容

为了从简单的值表中获取最大值,我可以在Django中编写以下查询:

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

生成的SQL是: '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。新查询变为:

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

这不再给我一个最大值,因为我被迫使用GROUP BY id。现在,我需要添加ORDER BYandLIMIT语句,以获取可以正常工作的否则简单的SQL语句的预期答案。

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"

PS 实际查询更为复杂(与该答案有些相关:https
:
//dba.stackexchange.com/a/86404/52114)


问题答案:

您应该使用自定义SQL而不是Manager.raw()方法:

from django.db import connection

cursor = connection.cursor()
cursor.execute('SELECT max(value) FROM mytable')
max_value = cursor.fetchone()[0]


 类似资料:
  • 在模型查询API不够用的情况下,你可以使用原始的sql语句。django提供两种方法使用原始sql进行查询:一种是使用Manager.raw()方法,进行原始查询并返回模型实例;另一种是完全避开模型层,直接执行自定义的sql语句。 警告 编写原始的sql语句时,应该格外小心。每次使用的时候,都要确保转义了参数中的任何控制字符,以防受到sql注入攻击。更多信息请参阅防止sql注入。 进行原始查询 r

  • 在用户模型中,我定义了关系: 它返回如何获得包括参数的完整查询? 我还定义了与post模型的关系: 如何使用参数查看完整的关系查询?

  • 问题内容: 我有一个具有复合主键的旧式数据库表。我认为我无法更改结构以包含代理键,因为编写了一些使用该表的代码。在django中,我无法使用该表,因为它没有主键(非复合键)。 Django模型是否支持复合主键?如果不是,是否有任何解决方法而不更改表的结构? PS我正在使用PostgreSQL。 问题答案: 试试下面类似的代码: 或者,如果你只想要唯一的混合字段: 编辑:我想指出,如果有3列,则此方

  • 问题内容: 我正在将MS-Access 2003与查询创建者一起使用。我从一个表()中选择所有内容,然后从另一表()中选择一个特定行()。我想从第二个表中选择另一行并将其连接起来。 查询 该查询的确在ID(字段)与where匹配的地方添加了字段。它像一种魅力。但是,我想在结果中添加另一行。我想获得行所在的位置(该部分实际上在工作)和行所在的位置。我将得到2行,并且当我要求()时,我希望将这两行连接

  • 问题内容: 有没有一种方法可以显示执行查询时Django正在运行的SQL? 问题答案: 请参阅文档FAQ:“如何查看Django正在运行的原始SQL查询? ” 包含SQL查询的列表: 查询集还具有包含要执行的查询的属性: 请注意,查询的输出不是有效的SQL,因为: “ Django实际上从未插值参数:它将查询和参数分别发送到数据库适配器,后者执行适当的操作。” 来自Django错误报告#17741

  • 问题内容: 我正在尝试使用类似于以下内容的原始sql查询 但是,这似乎在自己的单独事务中运行。因此,它会错过在service方法中之前完成的所有(未提交的)更改。 在当前事务中运行原始sql查询的最佳方法是什么? 问题答案: 上面的代码将创建一个新的连接,从而创建一个新的事务。您可以使用当前的Hibernate会话(注入sessionFactory)在当前事务中执行原始sql,如下所示。