class Log:
project = ForeignKey(Project)
msg = CharField(...)
date = DateField(...)
我想选择四个最新的日志条目,其中每个日志条目必须具有唯一的项目外键。我在谷歌搜索上尝试了这些解决方案,但它们都没有用,而且django文档对于查找来说并不是很好..
我试过像:
Log.objects.all().distinct('project')[:4]
Log.objects.values('project').distinct()[:4]
Log.objects.values_list('project').distinct('project')[:4]
但这不会返回任何内容或同一项目的Log条目..
任何帮助将不胜感激!
答案 0 :(得分:14)
查询不能像那样 - 在Django的ORM中或在底层的SQL中。如果要获取唯一ID,则只能查询ID。因此,您需要执行两个查询才能获取实际的日志条目。类似的东西:
id_list = Log.objects.order_by('-date').values_list('project_id').distinct()[:4]
entries = Log.objects.filter(id__in=id_list)
答案 1 :(得分:3)
实际上,您可以在SQL中获取project_ids。假设您希望具有最新日志条目的四个项目的唯一项目ID,则SQL将如下所示:
SELECT project_id, max(log.date) as max_date
FROM logs
GROUP BY project_id
ORDER BY max_date DESC LIMIT 4;
现在,您确实需要所有日志信息。在PostgreSQL 8.4及更高版本中,您可以使用窗口函数,但这不适用于其他版本/数据库,因此我将采用更复杂的方式:
SELECT logs.*
FROM logs JOIN (
SELECT project_id, max(log.date) as max_date
FROM logs
GROUP BY project_id
ORDER BY max_date DESC LIMIT 4 ) as latest
ON logs.project_id = latest.project_id
AND logs.date = latest.max_date;
现在,如果你拥有访问窗口函数的权限,它会更整洁(我想无论如何),并且执行起来肯定更快:
SELECT * FROM (
SELECT logs.field1, logs.field2, logs.field3, logs.date
rank() over ( partition by project_id
order by "date" DESC ) as dateorder
FROM logs ) as logsort
WHERE dateorder = 1
ORDER BY logs.date DESC LIMIT 1;
好吧,也许它不容易理解,但请相信我的话,它在大型数据库上运行速度更快。
我不完全确定如何转换为对象语法,或者即使它确实如此。此外,如果您想获得其他项目数据,则需要加入项目表。
答案 2 :(得分:0)
我知道这是一个老帖子,但在Django 2.0中,我认为你可以使用:
Log.objects.values('project').distinct().order_by('project')[:4]
答案 3 :(得分:0)
您需要两个查询集。好消息是它仍然会导致单次访问数据库(尽管涉及子查询)。
latest_ids_per_project = Log.objects.values_list(
'project').annotate(latest=Max('date')).order_by(
'-latest').values_list('project')
log_objects = Log.objects.filter(
id__in=latest_ids_per_project[:4]).order_by('-date')
这看起来有些令人费解,但实际上导致了一个令人惊讶的紧凑查询:
SELECT "log"."id",
"log"."project_id",
"log"."msg"
"log"."date"
FROM "log"
WHERE "log"."id" IN
(SELECT U0."id"
FROM "log" U0
GROUP BY U0."project_id"
ORDER BY MAX(U0."date") DESC
LIMIT 4)
ORDER BY "log"."date" DESC