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

如何在Django中按正反货币对组合分组查询ExchangeMarket模型?

解决方案

核心思路是给每个货币对生成标准化标识——不管base和quote的顺序如何,让同一货币对的正反方向拥有相同的分组键,再基于这个键聚合。

步骤1:生成标准化分组键并聚合

先导入需要的Django ORM工具:

from django.db.models import Case, When, F, IntegerField, ArrayAgg, Count

编写Queryset,通过Case/When生成两个标准化字段(取货币ID的最小值和最大值),再分组聚合:

# 生成标准化货币对,聚合同一组合(含正反方向)的所有主键
standardized_pairs = ExchangeMarket.objects.annotate(
    # 取base和quote中ID较小的货币作为统一基准
    min_currency=Case(
        When(base_currency__lt=F('quote_currency'), then=F('base_currency')),
        default=F('quote_currency'),
        output_field=IntegerField()
    ),
    # 取ID较大的货币作为统一配对
    max_currency=Case(
        When(base_currency__gt=F('quote_currency'), then=F('base_currency')),
        default=F('quote_currency'),
        output_field=IntegerField()
    )
).values('min_currency', 'max_currency').annotate(
    # 收集该组合下所有条目的主键
    pks=ArrayAgg('pk'),
    # 统计该组合下的条目数量(可选)
    total_count=Count('pk')
)

这段代码会把EUR/USD和USD/EUR归到同一组,它们的min_currency都是EUR的ID,max_currency都是USD的ID。

步骤2:筛选并获取完整条目

如果只想保留存在正反方向的组合(比如排除只有BTC/USD没有USD/BTC的条目),可以加过滤条件:

# 只保留有至少2条的组合(即存在正反对)
paired_pairs = standardized_pairs.filter(total_count__gt=1)

如果需要获取这些分组对应的完整ExchangeMarket对象,可以提取所有主键后查询:

# 提取所有相关主键
all_related_pks = []
for item in paired_pairs:
    all_related_pks.extend(item['pks'])

# 获取完整对象列表
target_markets = ExchangeMarket.objects.filter(pk__in=all_related_pks)

如果使用PostgreSQL数据库,还可以用Unnest简化主键提取:

from django.contrib.postgres.functions import Unnest

all_related_pks = paired_pairs.annotate(single_pk=Unnest('pks')).values_list('single_pk', flat=True)
target_markets = ExchangeMarket.objects.filter(pk__in=all_related_pks)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 07:32:53