You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django如何通过单次QuerySet查询获取不同concept_payment对应Temporal数据,减少查询次数

可行的优化方案

你完全可以通过单次查询拿到所有需要的数据,以下是两种常用实现方式:

方案1:单次查询后Python层分组(最简单通用)

公共过滤条件完全相同,你可以先一次性拉取所有符合公共条件的记录,再在内存中按concept_payment分组取首条即可:

from collections import defaultdict

# 仅执行1次数据库查询,拉取所有符合公共条件的记录
temporal_qs = Temporal.objects.filter(
    rate_name=rate_name,
    date_start__month__lte=month_apply,
    date_end__month__gte=month_apply
).order_by('concept_payment', 'order')  # 排序规则和你原有first()逻辑保持一致即可

# 按concept_payment分组,取每个分组的第一条记录
concept_map = defaultdict(lambda: None)
for item in temporal_qs:
    if concept_map[item.concept_payment] is None:
        concept_map[item.concept_payment] = item

使用时直接从字典取值即可,和原有逻辑完全兼容:

energy_concepts = concept_map.get('Energy')
demand_concepts = concept_map.get('Demand')
other_concepts = concept_map.get('Others')
taxes_concepts = concept_map.get('Taxes')

方案2:数据库层面直接取各分组首条(数据量大时更推荐)

如果符合条件的记录数量很大,不想把全量数据拉到内存,可以用Django的窗口函数直接在数据库层完成分组取首条的操作,仅返回每个concept_payment对应的第一条记录:

from django.db.models import F, Window
from django.db.models.functions import RowNumber

# 仅执行1次数据库查询,直接返回每个concept_payment的第一条记录
temporal_qs = Temporal.objects.filter(
    rate_name=rate_name,
    date_start__month__lte=month_apply,
    date_end__month__gte=month_apply
).annotate(
    row_num=Window(
        expression=RowNumber(),
        partition_by=[F('concept_payment')],
        order_by=F('order').asc(nulls_last=True)  # 排序规则和原有first()逻辑保持一致即可
    )
).filter(row_num=1)

# 转成字典方便后续取值
concept_map = {item.concept_payment: item for item in temporal_qs}

注意事项

  • 两种方案均仅执行1次数据库查询,远优于原有N次查询的实现
  • 代码中的order_by规则请和你原有first()逻辑的排序规则保持一致,若原来默认按主键排序,替换为id即可,避免返回结果和原有逻辑不一致
  • 如果需要获取所有concept_payment的可选值,直接取concept_map.keys()就能拿到当前符合条件的所有concept_payment取值,无需额外查询

内容的提问来源于stack exchange,提问作者Lmex89

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 17:57:06