为了账号安全,请及时绑定邮箱和手机立即绑定

如何汇总查询集中多个日期范围的总和?

如何汇总查询集中多个日期范围的总和?

至尊宝的传说 2021-06-07 09:17:25
是否可以将.sum()多个日期范围内的 s注释为一个QuerySet即,基本上将这些结合起来,所以每个对象都有每个日期范围的总和。query_set_week = DailyReports.objects.filter(    date__range=('2018-08-27', '2018-08-31')) \        .select_related('profile') \        .values('profile__user_id') \        .annotate(premium=Sum('total_field'),            first_name=F('profile__user__first_name'),            last_name=F('profile__user__last_name') \        .order_by('profile__agent_code')query_set_year = DailyReports.objects.filter(    date__range=('2018-01-01', '2018-08-31')) \        .select_related('profile') \        .values('profile__user_id') \        .annotate(premium=Sum('total_field'),            first_name=F('profile__user__first_name'),            last_name=F('profile__user__last_name') \        .order_by('profile__agent_code')两者都单独工作,但很难循环并显示数据(例如,用户 - 周总计 - 年度总计),因为有人可能在年过滤器中得到结果,但在周过滤器中没有。编辑:我目前能够使用.raw()大量 SQL 语句来实现我的目标,但我认为有一种更 Pythonic 的方法来做到这一点。
查看完整描述

2 回答

?
holdtom

TA贡献1805条经验 获得超10个赞

如果你想要不止一行,你可以像这样合并两个查询集:


base_qs = DailyReports.objects \

        .select_related('profile') \

        .values('profile__user_id') \

        .annotate(premium=Sum('total_field'),

            first_name=F('profile__user__first_name'),

            last_name=F('profile__user__last_name') \

        .order_by('profile__agent_code')


query_set_week = base_qs.filter(date__range=('2018-08-27', '2018-08-31'))

query_set_year = base_qs.filter(date__range=('2018-01-01', '2018-08-31'))


query_set_week_and_year = query_set_week.union(query_set_year)

query_set_week_and_year 应该给你两行,只执行一个 SQL 查询!


这里发生了什么事?

最重要的是,django 不会执行任何 SQL,直到对查询集进行评估(例如迭代、list()-ed、len()-ed等)。所以我们只是在构建 SQL,而不是执行看起来像 4 个查询的东西!


大多数数据库(我认为甚至是 sqlite)都有一些查询优化。即它将看到在两个查询中重复的事情并首先执行该位(以代码似乎正在执行的方式)。所以我们应该以(足够接近)最有效的方式来做这件事。


所以它不应该太耗时,我认为提供了一些可读的代码(?)!


查看完整回答
反对 回复 2021-06-09
?
慕神8447489

TA贡献1780条经验 获得超1个赞

据我所知,您似乎有两个几乎相同的查询,它们的区别仅在于date__range. 为什么不尝试使用-objectsOR在日期范围内使用SQLQ


您可以尝试以下操作:


query_set_week_and_year = DailyReports.objects \

    .filter(

        Q(date__range=('2018-08-27', '2018-08-31')) | Q(date__range=('2018-01-01', '2018-08-31')) \

    ).select_related('profile') \

    .values('profile__user_id') \

    .annotate(

        premium=Sum('total_field'),

        first_name=F('profile__user__first_name'),

        last_name=F('profile__user__last_name'

    ).order_by('profile__agent_code')

Q-objects 简而言之

Q 对象允许您通过二进制和运算符应用AND和OR过滤条件。(但您只需要它们进行操作,就像过滤器函数中的逗号一样)&|ORAND


例如,查找名字或姓氏以“A”开头的所有用户:


User.objects.filter(Q(firstname__startswith='A') | Q(lastname__startswith='A'))

边注

似乎第一行 date__range 包含在另一行中:2018-08-27-->2018-08-31在2018-01-01--> 内2018-08-31。如果这是您关心的两个日期范围,那么您只需要第二个查询..?


查看完整回答
反对 回复 2021-06-09
  • 2 回答
  • 0 关注
  • 166 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信