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

如何在不使用Raw方法的情况下将SQL查询转换为Django ORM查询?

将目标SQL转换为Django ORM写法(无Raw)

先假设你的BalanceHold模型结构和SQL字段对应(比如包含account_balance、hold_id、transaction_id、release_time、hold_type这些字段),以下是不用raw SQL的实现方式:

1. 导入ORM依赖

首先需要导入Django ORM的相关工具:

from django.db.models import Subquery, OuterRef, Max, Q

2. 构造分组聚合的子查询

原SQL的核心逻辑是按transaction_id分组,分别处理两种release_time的场景,取每组的极值:

  • 当release_time为null时,取该组最大的hold_type
  • 当release_time不为null时,取该组最大的release_time

先构造这两个场景的子查询:

# 场景1:release_time为null时,每组的最大hold_type
null_release_max_hold = BalanceHold.objects.filter(
    transaction_id=OuterRef('transaction_id'),
    account_balance=X,  # 替换成你实际的X值(比如账户余额实例或ID)
    release_time__isnull=True
).values('transaction_id').annotate(max_type=Max('hold_type')).values('max_type')

# 场景2:release_time不为null时,每组的最大release_time
non_null_release_max_time = BalanceHold.objects.filter(
    transaction_id=OuterRef('transaction_id'),
    account_balance=X,
    release_time__isnull=False
).values('transaction_id').annotate(max_time=Max('release_time')).values('max_time')

3. 筛选符合条件的hold_id

接下来构造子查询,找出每个transaction_id下满足条件的记录(要么是null场景下hold_type等于组内最大值,要么是非null场景下release_time等于组内最大值),并取出这些记录的hold_id:

valid_hold_ids = BalanceHold.objects.filter(
    transaction_id=OuterRef('transaction_id'),
    account_balance=X,
    # 两种场景的或条件
    Q(
        release_time__isnull=True,
        hold_type=Subquery(null_release_max_hold)
    ) | Q(
        release_time__isnull=False,
        release_time=Subquery(non_null_release_max_time)
    )
).values('hold_id')

4. 执行最终查询

最后外层查询筛选出account_balance=X且hold_id在上述子查询结果中的所有记录:

final_result = BalanceHold.objects.filter(
    account_balance=X,
    hold_id__in=Subquery(valid_hold_ids)
)

注意事项

  • 把代码中的X替换成你实际的account_balance值(比如外键对象或者对应的ID)
  • 如果hold_id是模型的主键,逻辑可以进一步简化,但上述写法完全匹配你原SQL的逻辑
  • 为了提升查询性能,建议给transaction_id、account_balance、release_time这些字段添加数据库索引

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 11:20:28