Django在GROUP BY之后获得Max的ID

时间:2018-02-04 19:48:49

标签: python sql django django-queryset

我有两种模式:

Forum: pk (ID)
Thread: pk (ID), last_activity (datetime), forum (foreign key)

我想检索所有最新的线程,按forum分组,除此之外至少获取每个最新线程的ID。

这是我尝试的内容:

Thread.objects.values(
    'forum'
).annotate(
    latest=Max('last_activity')
).order_by()

这是它产生的东西:

<QuerySet [
    {'forum': 1, 'latest': datetime.datetime(...)}, 
    {'forum': 2, 'latest': datetime.datetime(...)}, 
    {'forum': 3, 'latest': datetime.datetime(...)}, 
    {'forum': 4, 'latest': datetime.datetime(...)}, 
    {'forum': 5, 'latest': datetime.datetime(...)}, 
    {'forum': 6, 'latest': datetime.datetime(...)}
]>

对于查询集中的每个条目,它应该另外生成的是具有最大值latest的线程的ID。这是一个示例条目:

{'forum': 6, 'latest': datetime.datetime(...), thread_id: 60}

这是它生成的原始查询:

SELECT "forumapp_thread"."forum_id",
       MAX("forumapp_thread"."last_activity") AS "latest"
FROM "forumapp_thread"
GROUP BY "forumapp_thread"."forum_id"
ORDER BY "forumapp_thread"."forum_id" ASC

这是我想要的查询:

SELECT "forumapp_thread"."forum_id",
       "forumapp_thread"."id",
       MAX("forumapp_thread"."last_activity") AS "latest"
FROM "forumapp_thread"
GROUP BY "forumapp_thread"."forum_id"
ORDER BY "forumapp_thread"."forum_id" ASC

2 个答案:

答案 0 :(得分:0)

您应该能够使用子查询(https://docs.djangoproject.com/en/2.0/ref/models/expressions/#subquery-expressions)实现您想要的目标。

from django.db.models import OuterRef, Subquery
latest = Thread.objects.filter(forum=OutRef('pk')).order_by(-'last_activity')
Forum.objects.annotate(latest=Subquery(latest.values('last_activity')[:1]), thread_id=Subquery(latest.values('pk')[:1]))

我还没有对它进行过测试,但它应该有效。

答案 1 :(得分:0)

对于这种情况,我们可以F个对象。

from django.db.models import F, Max

Thread.objects.values('forum').annotate(
    latest=Max('last_activity'), thread_id=F('id')
).order_by()

参考:https://docs.djangoproject.com/en/2.0/ref/models/expressions/#f-expressions