如何将含NOT IN子查询的SQL正确转换为适配大表的Peewee代码
正确Peewee实现方案
方案1:子查询写法(和你给出的原生SQL完全等价)
Peewee的not_in运算符原生支持传入Select查询对象,会直接生成嵌套子查询的SQL,不会将B表的查询结果拉取到应用内存,完全适配千万级数据量的场景。
你之前的写法只是存在括号配对的语法错误,导致生成的SQL不符合预期,所以返回结果和原生SQL不一致,修正后的代码如下:
# 写法1:直接调用count()方法 count = A.select().where( A.id.not_in(B.select(B.package_id).distinct()) ).count() # 写法2:手动指定COUNT函数,用scalar()拿结果,更直观 from peewee import fn count = A.select(fn.COUNT('*')).where( A.id.not_in(B.select(B.package_id).distinct()) ).scalar()
你可以通过print(A.select(...).sql())打印生成的SQL,验证和你写的原生SQL完全一致。
方案2:LEFT JOIN写法(部分数据库下性能更优)
LEFT JOIN + 空值判断的写法完全可以实现需求,对于很多数据库来说,这种写法的执行性能比NOT IN子查询更好,尤其是B表的package_id字段建有索引的情况下:
from peewee import fn count = A.select(fn.COUNT(A.id)).join( B, on=(A.id == B.package_id), join_type='LEFT' ).where(B.package_id.is_null()).scalar()
这个写法的逻辑是左连接B表后,所有B表相关字段为空的记录就是A表中id不存在于B表package_id的记录,直接计数即可,同样不会有应用层的数据拉取开销。
内容的提问来源于stack exchange,提问作者Larytet
相关产品推荐
相关产品推荐

