【发布时间】: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 中可用的结果?
【问题讨论】:
标签: python mysql django orm django-orm