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

Django ORM如何实现双列匹配的WHERE IN子查询

Django ORM 实现多字段 WHERE IN 子查询方案

Django ORM 完全支持多字段组合匹配的WHERE IN查询,根据使用的Django版本不同,可以选择以下两种和原生SQL语义完全等价的实现方式,不会出现字段匹配错位的问题。


方案1:Django 3.2+ 原生多列IN支持(与原生SQL逻辑完全一致)

Django 3.2版本新增了Tuple表达式支持多列组合匹配,写法最贴近原生SQL逻辑:

from django.db.models import Subquery
from django.db.models.expressions import Tuple

# 构造子查询:筛选指定客户持有的许可证的version、type字段
customer_licenses = License.objects.filter(
    company_id="6f65e5cc-cd1f-4888-a236-38295bae393a"
).values("version", "type")

# 主查询:匹配version+type组合在子查询结果内的版本详情记录
version_detail_list = VersionDetails.objects.filter(
    Tuple("version", "type")__in=Subquery(customer_licenses)
)

该写法生成的SQL和给出的原生语句结构完全一致。


方案2:全版本兼容写法(基于EXISTS关联,推荐低版本使用)

如果Django版本低于3.2,可以用Exists关联子查询实现完全相同的语义,所有Django版本都支持,且多数数据库下执行效率和IN查询相当:

from django.db.models import Exists, OuterRef

version_detail_list = VersionDetails.objects.annotate(
    match_license=Exists(
        License.objects.filter(
            company_id="6f65e5cc-cd1f-4888-a236-38295bae393a",
            version=OuterRef("version"),
            type=OuterRef("type")
        )
    )
).filter(match_license=True)

注意事项

  • 不要尝试分开为两个字段单独写__in条件,类似下面的错误写法会出现字段组合错位:
# 错误写法:会匹配到(version=v1, type=t2)这类不存在于子查询的错误组合
bad_case = VersionDetails.objects.filter(
    version__in=customer_licenses.values("version"),
    type__in=customer_licenses.values("type")
)

这种写法相当于对两个字段分别做范围匹配,而非组合匹配,返回结果会多出不符合要求的记录。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 06:06:31