我可以在 django 1.3 的 orm 中控制 GROUP BY 吗?
Posted
技术标签:
【中文标题】我可以在 django 1.3 的 orm 中控制 GROUP BY 吗?【英文标题】:Can I control the GROUP BY in django 1.3's orm? 【发布时间】:2011-10-13 16:51:58 【问题描述】:我认为这最好用一个例子来解释。
数据如下所示:
|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|
我希望能够从每个项目的最新运行中获取整个记录集。 SQL 查询看起来像这样:
SELECT *, MAX("run"."start_time")
FROM "run"
LEFT OUTER JOIN "project" ON ("run"."project_id" = "project"."id")
GROUP BY "project"."id"
这将为我返回项目最新运行的两个表中的所有列,这很棒,这正是我所需要的。
因此,在尝试在 django 1.3 中找到等效的 django orm 时,我根本找不到合适的方法。如果我这样做:
Run.objects.annotate(Max('start_time'))
生成的 SQL 查询将如下所示:
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"
这不会返回正确的结果,因为 group by 不符合我的要求。我相信在以前版本的 django 中,以下内容会在查询中正确明确地设置 group by 子句,但在 1.3 中似乎不起作用:
q = Run.objects.annotate(Max('start_time'))
q.query.group_by = [("project", "id")]
在 1.3 中,这会生成与不手动修改查询中的 group_by 属性完全相同的查询。
我还尝试了这种基于 .values() 在 annotate() 调用前后的记录行为的合乎逻辑的方法,但它没有按预期工作。当我尝试这个时:
q = Run.objects.values('project__id').annotate(Max('start_time')).values('id')
我最终得到了这样的查询:
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"
如果没有以下任何一项,谁能指出我正在做的事情的正确方法:
使用原始 sql - 当我必须经常生成自己的查询时,使用 orm 有什么意义? 使用 .extra(select = 'latest': 'somequery') - 当没有子查询的完全有效的查询可以给我想要的东西时,为什么我必须使用子查询。 使用多个查询来获取相同的数据 - 同样,为什么我必须进行多个查询才能获得 1 中可用的结果?【问题讨论】:
【参考方案1】:tl;dr:Django 确实允许您控制 group by 子句,但它限制它在所有 SQL 风格中工作,所以我不能做我想做的事。
有人向我指出,我尝试使用 django ORM 生成的原始查询实际上并不适用于所有类型的 SQL。这是我正在寻找的查询的复习:
SELECT *, MAX("run"."start_time")
FROM "run"
LEFT OUTER JOIN "project" ON ("run"."project_id" = "project"."id")
GROUP BY "project"."id"
如果一个人试图选择 MSSQL 中 GROUP BY 中没有的东西,他们实际上会得到一个错误。所以在我看来,django 实际上不应该让我生成这样的查询,而我实际上是在试图错误地解决我的问题。
【讨论】:
【参考方案2】:这在文档的注释部分相当简单和详细,在以前的任何版本中都不能手动设置分组依据。
YourModel.objects.values('this_is_your_group_by', 'even_a_second_field').annotate(sum=Sum('your_field'))
【讨论】:
这不会返回每一行的整个记录集。它只会给我值列表中列的值。这意味着我无法在不按列分组的情况下从列中获取数据,不幸的是,我需要运行 ID。 `values('groupings,...).annotate().values('more_fields_to_show_here') 确保将注释添加的字段名称添加到注释后的值术语中 你应该真的读完了docs.djangoproject.com/en/1.3/topics/db/aggregation/… 我忘了提到这是我尝试的第一种方法,因为根据文档,这似乎是合乎逻辑的方法。它并没有按预期工作。后面的值调用中的所有值最终都在 group_by 子句中。我已经阅读了文档,除非我做错了什么,否则它似乎没有按预期工作。我将更新原始问题以说明我已经尝试过这个以及结果是什么,这只是我写问题时的疏忽。以上是关于我可以在 django 1.3 的 orm 中控制 GROUP BY 吗?的主要内容,如果未能解决你的问题,请参考以下文章