如何用Django ORM筛选A表无匹配f1/f2的B表数据?
问题描述
现有两个Django模型:
class A(models.Model): f1 = models.CharField() f2 = models.IntegerField() f3 = models.BooleanField() class B(models.Model): f1 = models.CharField() f2 = models.IntegerField() f3 = models.DecimalField()
现有数据:
A表数据:
A(f1='rat', f2=100, f3=True) A(f1='cat', f2=200, f3=True) A(f1='dog', f2=300, f3=False)
B表数据:
B(f1='eagle', f2=100, f3=3.14) B(f1='cat', f2=200, f3=9.81) B(f1='dog', f2=300, f3=100.500)
需求:筛选出B表中f1和f2字段组合在A表中无匹配数据的对象,预期结果:
B(f1='eagle', f2=100, f3=3.14)
请问能否通过Django ORM实现该查询?尝试过子查询但未找到合适示例。
解决方案
完全可以通过Django ORM实现,以下是两种常用实现方式:
方法一:exclude结合多字段条件匹配
直接排除B表中f1+f2组合在A表中存在的记录:
from django.db.models import Q # 获取A表中所有(f1, f2)的有效组合 a_pairs = A.objects.values_list('f1', 'f2') # 构造匹配所有组合的Q条件 match_conditions = Q() for f1_val, f2_val in a_pairs: match_conditions |= Q(f1=f1_val, f2=f2_val) # 排除匹配成功的记录,得到目标结果 result = B.objects.exclude(match_conditions)
方法二:Exists子查询(大数据量推荐)
利用Django的Exists生成高效的SQL子查询,直接判断当前B记录的f1+f2是否在A表中存在,性能优于第一种方法:
from django.db.models import Exists, OuterRef # 定义子查询:匹配当前B记录的f1和f2 subquery = A.objects.filter(f1=OuterRef('f1'), f2=OuterRef('f2')) # 给B表记录添加是否匹配的标记,再筛选无匹配的记录 result = B.objects.annotate(has_match=Exists(subquery)).filter(has_match=False)
两种方法均可得到预期结果,其中Exists子查询会生成更高效的SQL语句,避免内存处理大量数据对,适合数据量较大的场景。
内容的提问来源于stack exchange,提问作者Виталий Никоненко
相关产品推荐
相关产品推荐

