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

Django中如何高效获取每个Medecin对应的最新Visite记录

Django查询每个医生对应的最新拜访记录优化方案

你当前的写法属于典型的N+1查询问题:1次查询拉取所有医生数据,之后遍历每个医生时都要单独发起1次查询拉取对应拜访记录,医生数量多时性能会指数级下降。以下是两种高效实现方案:

方案1:通用子查询方案(兼容所有数据库,仅需2次查询)

使用Django ORM的Subquery注解实现,不需要依赖特定数据库,适用范围最广:

from django.db.models import OuterRef, Subquery

# 构造子查询:匹配外部医生ID,按关联报告的创建时间倒序,取最新1条拜访记录的主键
latest_visite_sub = Visite.objects.filter(
    medecin_id=OuterRef('pk')
).order_by('-rapport__added').values('pk')[:1]

# 给所有医生注解最新拜访记录ID,过滤掉没有拜访记录的医生
medecins = Medecin.objects.annotate(
    latest_visite_id=Subquery(latest_visite_sub)
).filter(latest_visite_id__isnull=False)

# 一次性拉取所有最新拜访记录
last_visites = Visite.objects.filter(id__in=medecins.values_list('latest_visite_id', flat=True))

如果你的拜访记录主键是自增的、插入顺序等于时间顺序,也可以直接按-pk排序,省略关联报告的查询,性能更高:

latest_visite_sub = Visite.objects.filter(
    medecin_id=OuterRef('pk')
).order_by('-pk').values('pk')[:1]

方案2:PostgreSQL专属方案(仅需1次查询,性能最高)

如果你使用PostgreSQL作为数据库,可以直接用distinct的专属语法,一次查询拿到所有结果:

last_visites = Visite.objects.order_by(
    'medecin_id', '-rapport__added'
).distinct('medecin_id')

额外优化建议

  • 如果需要同时获取医生和对应拜访记录的信息,可以在查询Visite时加上select_related('medecin'),一次查询把关联的医生数据也拉取回来,避免后续额外请求:
    last_visites = Visite.objects.select_related('medecin').order_by(
        'medecin_id', '-rapport__added'
    ).distinct('medecin_id')
    
  • 建议给Visite表的medecin_id和rapport_id加联合索引,可大幅提升查询速度。
  • 你原来的写法没有处理医生没有拜访记录的情况,直接取[-1]会抛出IndexError,上述方案默认过滤掉了无拜访记录的医生,如需保留可以删除filter(latest_visite_id__isnull=False)条件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 11:45:03