我认为最好用一个例子来解释。
以下是数据的样子:
|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 Query看起来像这样:
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属性。
我也是根据annotate()调用之前和之后记录的.values()行为的逻辑方式尝试过的,但它没有按预期工作。当我尝试这个时:
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"
在没有以下任何内容的情况下,任何人都可以指出我正确的方式来做我正在做的事情:
答案 0 :(得分: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实际上不应该让我生成这样的查询,我基本上是在尝试不正确地解决我的问题。
答案 1 :(得分:0)
这在文档的注释部分中相当简单和详细,并且没有以前的版本可以手动设置组。
YourModel.objects.values('this_is_your_group_by', 'even_a_second_field').annotate(sum=Sum('your_field'))