如何用SQLAlchemy查询子表含tunnel_id为Null的父表Site数据
最优实现方案(推荐)
使用exists构造半连接查询,性能最高,无需额外去重:
from sqlalchemy import exists # 构造子查询:匹配当前Site存在tunnel_id为NULL的关联Tunnel记录 subquery = exists().where( Tunnel.site_id == Site.id, Tunnel.tunnel_id.is_(None) ) # Flask-SQLAlchemy 写法(Flask开发者直接用这个即可) target_sites = Site.query.filter(subquery).all() # 原生SQLAlchemy 会话写法(可选参考) # target_sites = session.query(Site).filter(subquery).all()
该方案的优势是数据库扫描到任意一条符合条件的Tunnel记录就会停止匹配对应Site,不会产生冗余数据,也不需要额外去重,你之前为tunnel_id建立的索引可以直接被该查询命中,查询效率极高。
备选实现方案(适合小数据量场景)
如果更熟悉JOIN写法,可以搭配distinct去重实现:
target_sites = Site.query.join(Tunnel).filter(Tunnel.tunnel_id.is_(None)).distinct().all()
注意:因为一个Site可能关联多条符合条件的Tunnel,直接JOIN会返回重复的Site记录,必须加distinct()做去重处理,性能略低于exists方案。
初学者注意事项
- 判空必须使用
is_(None)语法,不要写== None,后者无法生成正确的IS NULLSQL语句 - 上述两种写法返回的结果都是符合条件的Site对象列表,可直接按业务逻辑使用
内容的提问来源于stack exchange,提问作者Shahroz Pervaz
相关产品推荐
相关产品推荐

