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

如何用Django ORM实现分组聚合,获取各证券最新价格(无需原生SQL)

用Django ORM查询每种证券的最新价格

没问题!我来帮你搞定这个需求——不用写原生SQL,纯靠Django ORM就能实现每种证券最新价格的查询。先假设你的模型结构大概是这样(如果和你的实际模型有出入,你可以对应调整字段名就行):

from django.db import models

# 证券主表
class Security(models.Model):
    code = models.CharField(max_length=10, unique=True, verbose_name='证券代码')
    name = models.CharField(max_length=50, verbose_name='证券名称')

# 价格记录表(每条记录对应某一时刻的证券价格)
class PriceRecord(models.Model):
    security = models.ForeignKey(Security, on_delete=models.CASCADE, verbose_name='关联证券')
    price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='价格')
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='记录时间')

下面给你两种常用且高效的实现方式:

方法一:子查询(推荐,Django 1.11+支持)

这个方法逻辑清晰,而且性能不错,尤其是数据量较大的时候。核心思路是:先为每个证券找到它最新的价格记录时间(或记录ID),再筛选出对应这条时间/ID的价格记录。

方式1:按记录时间筛选

from django.db.models import Subquery, OuterRef

# 子查询:获取每个证券的最新价格记录时间
latest_time_subquery = PriceRecord.objects.filter(
    security=OuterRef('pk')  # 关联外部查询的Security主键
).order_by('-created_at').values('created_at')[:1]  # 按时间倒序,取第一条的时间

# 查询证券并关联最新价格
securities_with_latest_price = Security.objects.annotate(
    latest_price_time=Subquery(latest_time_subquery)
).filter(
    # 筛选出该证券下时间等于最新时间的价格记录
    pricerecord__created_at=models.F('latest_price_time')
).values('code', 'name', 'pricerecord__price')  # 指定要返回的字段

# 遍历结果
for item in securities_with_latest_price:
    print(f"证券:{item['code']}-{item['name']},最新价格:{item['pricerecord__price']}")

方式2:按记录ID筛选(避免同一时间多条记录的问题)

如果你的系统可能出现同一证券在同一时间有多条价格记录的情况,用ID筛选更准确(因为ID是自增的,最新插入的记录ID更大):

from django.db.models import Subquery, OuterRef

# 子查询:获取每个证券的最新价格记录ID
latest_record_id_subquery = PriceRecord.objects.filter(
    security=OuterRef('pk')
).order_by('-created_at', '-id').values('id')[:1]  # 先按时间倒序,再按ID倒序

# 直接查询最新的价格记录集合
latest_price_records = PriceRecord.objects.filter(
    id__in=Subquery(latest_record_id_subquery)
).select_related('security')  # 关联证券表,避免N+1查询

# 遍历结果
for record in latest_price_records:
    print(f"证券:{record.security.code}-{record.security.name},最新价格:{record.price}")

方法二:用annotate+Max聚合

这种方法先通过聚合得到每个证券的最新记录时间,再筛选出对应记录:

from django.db.models import Max

# 第一步:获取每个证券的最新价格记录时间
latest_time_map = PriceRecord.objects.values('security').annotate(
    latest_time=Max('created_at')
)

# 第二步:把(证券ID, 最新时间)转成元组列表,用来筛选
filter_tuples = [(item['security'], item['latest_time']) for item in latest_time_map]

# 第三步:筛选出符合条件的价格记录
latest_price_records = PriceRecord.objects.filter(
    # 匹配每个(证券ID, 时间)组合
    models.Q(security=models.F('security'), created_at=models.F('latest_time'))
).filter(
    security__in=[t[0] for t in filter_tuples],
    created_at__in=[t[1] for t in filter_tuples]
).distinct().select_related('security')

# 遍历结果和上面一样,这里就省略啦

如果你的模型字段名和示例不一样,比如证券代码字段叫stock_code,记录时间叫update_time,只要对应替换字段名就行,逻辑都是通用的~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 08:50:14