在Django中筛选收支金额匹配的非零记录(附MySQL示例)
在Django中筛选收支金额匹配的记录(数万条数据场景)
需求分析
需要筛选出满足以下条件的记录:
- 排除收入或支出为0.00且无对应匹配金额的记录
- 若记录收入>0.00,则表中存在至少一条支出等于该收入金额的记录
- 若记录支出>0.00,则表中存在至少一条收入等于该支出金额的记录
前提假设
假设你的Django模型定义如下:
class Record(models.Model): id = models.AutoField(primary_key=True) income = models.DecimalField(max_digits=10, decimal_places=2) expense = models.DecimalField(max_digits=10, decimal_places=2)
实现方案
方案一:Django ORM 高效实现(推荐)
使用Exists子查询和Q对象组合条件,半连接查询性能更优,适配数万条数据场景:
from django.db.models import Q, Exists, OuterRef # 子查询:检查当前收入金额是否存在对应的有效支出记录 has_matching_expense = Record.objects.filter( expense=OuterRef('income'), expense__gt=0 ) # 子查询:检查当前支出金额是否存在对应的有效收入记录 has_matching_income = Record.objects.filter( income=OuterRef('expense'), income__gt=0 ) # 筛选符合条件的记录 matched_records = Record.objects.filter( Q(income__gt=0, exists=Exists(has_matching_expense)) | Q(expense__gt=0, exists=Exists(has_matching_income)) )
方案二:原生SQL实现
如果需要更灵活的查询控制,可直接使用原生SQL:
from django.db import connection with connection.cursor() as cursor: cursor.execute(""" SELECT r.* FROM your_table r WHERE (r.income > 0 AND EXISTS (SELECT 1 FROM your_table WHERE expense = r.income AND expense > 0)) OR (r.expense > 0 AND EXISTS (SELECT 1 FROM your_table WHERE income = r.expense AND income > 0)); """) # 可选:将查询结果转换为Record模型实例 matched_records = Record.objects.raw(cursor.query)
性能优化建议
针对数万条数据,建议给income和expense字段添加数据库索引,大幅提升查询速度:
# 修改模型字段,添加索引配置 income = models.DecimalField(max_digits=10, decimal_places=2, db_index=True) expense = models.DecimalField(max_digits=10, decimal_places=2, db_index=True)
添加索引后,执行python manage.py makemigrations和python manage.py migrate完成索引创建。
结果验证
针对你提供的示例数据,执行上述代码后,将得到id为1、3、4、6、7的记录,与预期结果完全一致。
内容的提问来源于stack exchange,提问作者yuong
相关产品推荐
相关产品推荐

