【问题标题】:Getting actual model instance after aggregating by maximum value (Django)按最大值聚合后获取实际模型实例(Django)
【发布时间】:2021-07-21 14:01:44
【问题描述】:

鉴于以下模型:

浏览器

id
1
2
3

会话

id last_activity browser
1 2021-01-01 1
2 2021-01-02 1
3 2021-01-03 2
4 2021-01-04 2
5 2021-01-05 3

我想为每个唯一的Browser 选择具有最新last_activitySession 对象,在本例中为:

会话

id
2
4
5

我试过Session.objects.values('browser').annotate(Max('last_activity')),但这并没有给出实际的Session 实例。这在 Django 中可行吗?

如果可能,我想避免使用原始 SQL,并避免循环查询集。

注意:这是一个 sqlite 后端,所以DISTINCT ON 不起作用。

【问题讨论】:

    标签: python django django-models django-queryset


    【解决方案1】:

    我找到了以下解决方案,不幸的是它使用了多个SELECTs

    query = Session.objects.filter(browser=OuterRef('pk')).order_by('-last_activity')
    query = Browser.objects.annotate(session_id=Subquery(query.values('pk')[:1]))
    query = Session.objects.filter(id__in=query.values('session_id'))
    print(query)
    

    【讨论】:

      【解决方案2】:

      我不太明白你的问题

      latest_browser = Session.objects.order_by("-last_activity").first().browser
      

      获取每个浏览器的最后一个会话:

      latest_sessions = []
      for browser in Browser.objects.all():
          latest_sessions.append(browser.session_set.order_by("-last_activity").first())
      

      或者如果你只想要一个查询:

      id_browsers = Session.objects.values_list('browser', flat=True).annotate(Max('last_activity'))
      sessions = Session.objects.filter(browser_id__in=id_browsers)
      

      【讨论】:

      • 我想避免在一个循环中进行多个查询。 distinct() 的查询解决方案不起作用,所有sessions 都列出来了。
      • 我收到了django.db.utils.OperationalError: sub-select returns 2 columns - expected 1。此外,这不会选择具有最新 last_activity 的选项,因为多个会话可以使用相同的浏览器。
      猜你喜欢
      • 1970-01-01
      • 2011-01-05
      • 1970-01-01
      • 1970-01-01
      • 2019-01-15
      • 1970-01-01
      • 2012-10-16
      • 2017-05-02
      • 1970-01-01
      相关资源
      最近更新 更多